Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2709 lines
98 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. ( void ) 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. ( void ) va_arg(Args, LPWSTR);
  601. break;
  602. case ADSTYPE_BOOLEAN:
  603. case ADSTYPE_INTEGER:
  604. ( void ) va_arg(Args, DWORD);
  605. break;
  606. case ADSTYPE_OCTET_STRING:
  607. (void ) va_arg(Args, LPBYTE);
  608. (void ) va_arg(Args, DWORD); // additional DWORD values for these..
  609. break;
  610. case ADSTYPE_LARGE_INTEGER:
  611. (void ) va_arg(Args, LONG);
  612. (void ) va_arg(Args, LONG); // 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(defines)
  699. #define StoreCreateObject StoreCreateObjectVA
  700. //EndExport(defines)
  701. //BeginExport(function)
  702. DWORD
  703. StoreDeleteObject(
  704. IN OUT LPSTORE_HANDLE hStore,
  705. IN DWORD Reserved,
  706. IN LPWSTR ObjectName
  707. ) //EndExport(function)
  708. {
  709. DWORD Result;
  710. HRESULT hResult;
  711. AssertRet(hStore, ERROR_INVALID_PARAMETER);
  712. AssertRet(ObjectName, ERROR_INVALID_PARAMETER);
  713. hResult = ADSIDeleteDSObject(
  714. hStore->ADSIHandle,
  715. ObjectName
  716. );
  717. if( FAILED(hResult) ) return ConvertHresult(hResult);
  718. return ERROR_SUCCESS;
  719. }
  720. //BeginExport(function)
  721. //DOC StoreDeleteThisObject deletes the object defined by hStore,StoreGetType and ADsPath.
  722. //DOC The refer to the object just the same way as for StoreGetHandle.
  723. DWORD
  724. StoreDeleteThisObject( // delete an object
  725. IN LPSTORE_HANDLE hStore, // point of anchor frm which reference is done
  726. IN DWORD Reserved, // must be zero, reserved for future use
  727. IN DWORD StoreGetType, // path is relative, absolute or diff server?
  728. IN LPWSTR Path // ADsPath to the object or relative path
  729. ) //EndExport(function)
  730. {
  731. HRESULT hResult;
  732. DWORD Result;
  733. DWORD Size;
  734. LPWSTR ConvertedPath, ChildNameStart,ChildNameEnd;
  735. LPWSTR ChildName;
  736. HANDLE ParentObject;
  737. AssertRet(hStore, ERROR_INVALID_PARAMETER);
  738. AssertRet(hStore->Location, ERROR_INVALID_PARAMETER);
  739. AssertRet(Path, ERROR_INVALID_PARAMETER);
  740. Result = ConvertPath(hStore, StoreGetType, Path, &ConvertedPath);
  741. if( ERROR_SUCCESS != Result ) return Result;
  742. Require(ConvertedPath);
  743. ChildNameStart = wcschr(ConvertedPath, L'/'); Require(ChildNameStart); ChildNameStart++;
  744. ChildNameStart = wcschr(ChildNameStart, L'/'); Require(ChildNameStart); ChildNameStart++;
  745. if( wcschr(ChildNameStart, L'/') ) {
  746. ChildNameStart = wcschr(ChildNameStart, L'/');
  747. Require(ChildNameStart); ChildNameStart++;
  748. }
  749. ChildNameEnd = wcschr(ChildNameStart, L','); Require(ChildNameEnd); *ChildNameEnd++ = L'\0';
  750. ChildName = MemAlloc((DWORD)((LPBYTE)ChildNameEnd - (LPBYTE)ChildNameStart));
  751. if( NULL == ChildName ) {
  752. MemFree(ConvertPath);
  753. return ERROR_NOT_ENOUGH_MEMORY;
  754. }
  755. memcpy(ChildName, ChildNameStart, (int)((LPBYTE)ChildNameEnd - (LPBYTE)ChildNameStart));
  756. wcscpy(ChildNameStart, ChildNameEnd); // remove child name from ConvertPath
  757. hResult = ADSIOpenDSObject( // open the parent object
  758. ConvertedPath,
  759. hStore->UserName,
  760. hStore->Password,
  761. hStore->AuthFlags,
  762. &ParentObject
  763. );
  764. MemFree(ConvertedPath);
  765. if( FAILED(hResult) ) {
  766. MemFree(ChildName);
  767. return ConvertHresult(hResult);
  768. }
  769. hResult = ADSIDeleteDSObject( // delete the required child object
  770. ParentObject,
  771. ChildName
  772. );
  773. MemFree(ChildName);
  774. ADSICloseDSObject(ParentObject); // free up handles and memory
  775. if( FAILED(hResult) ) return ConvertHresult(hResult);
  776. return ERROR_SUCCESS; // : need to have better error messages than this
  777. }
  778. //================================================================================
  779. // dhcp specific stuff follow here..
  780. //================================================================================
  781. //BeginExport(typedef)
  782. typedef struct _EATTRIB { // encapsulated attribute
  783. unsigned int Address1_present : 1;
  784. unsigned int Address2_present : 1;
  785. unsigned int Address3_present : 1;
  786. unsigned int ADsPath_present : 1;
  787. unsigned int StoreGetType_present : 1;
  788. unsigned int Flags1_present : 1;
  789. unsigned int Flags2_present : 1;
  790. unsigned int Dword1_present : 1;
  791. unsigned int Dword2_present : 1;
  792. unsigned int String1_present : 1;
  793. unsigned int String2_present : 1;
  794. unsigned int String3_present : 1;
  795. unsigned int String4_present : 1;
  796. unsigned int Binary1_present : 1;
  797. unsigned int Binary2_present : 1;
  798. DWORD Address1; // character "i"
  799. DWORD Address2; // character "j"
  800. DWORD Address3; // character "k"
  801. LPWSTR ADsPath; // character "p" "r" "l"
  802. DWORD StoreGetType; // "p,r,l" ==> sameserver, child, otherserver
  803. DWORD Flags1; // character "f"
  804. DWORD Flags2; // character "g"
  805. DWORD Dword1; // character "d"
  806. DWORD Dword2; // character "e"
  807. LPWSTR String1; // character "s"
  808. LPWSTR String2; // character "t"
  809. LPWSTR String3; // character "u"
  810. LPWSTR String4; // character "v"
  811. LPBYTE Binary1; // character "b"
  812. DWORD BinLen1; // # of bytes of above
  813. LPBYTE Binary2; // character "d"
  814. DWORD BinLen2; // # of bytes of above
  815. } EATTRIB, *PEATTRIB, *LPEATTRIB;
  816. //EndExport(typedef)
  817. //BeginExport(defines)
  818. #define IS_ADDRESS1_PRESENT(pEA) ((pEA)->Address1_present)
  819. #define IS_ADDRESS1_ABSENT(pEA) (!IS_ADDRESS1_PRESENT(pEA))
  820. #define ADDRESS1_PRESENT(pEA) ((pEA)->Address1_present = 1 )
  821. #define ADDRESS1_ABSENT(pEA) ((pEA)->Address1_present = 0 )
  822. #define IS_ADDRESS2_PRESENT(pEA) ((pEA)->Address2_present)
  823. #define IS_ADDRESS2_ABSENT(pEA) (!IS_ADDRESS2_PRESENT(pEA))
  824. #define ADDRESS2_PRESENT(pEA) ((pEA)->Address2_present = 1 )
  825. #define ADDRESS2_ABSENT(pEA) ((pEA)->Address2_present = 0 )
  826. #define IS_ADDRESS3_PRESENT(pEA) ((pEA)->Address3_present)
  827. #define IS_ADDRESS3_ABSENT(pEA) (!IS_ADDRESS3_PRESENT(pEA))
  828. #define ADDRESS3_PRESENT(pEA) ((pEA)->Address3_present = 1 )
  829. #define ADDRESS3_ABSENT(pEA) ((pEA)->Address3_present = 0 )
  830. #define IS_ADSPATH_PRESENT(pEA) ((pEA)->ADsPath_present)
  831. #define IS_ADSPATH_ABSENT(pEA) (!IS_ADSPATH_PRESENT(pEA))
  832. #define ADSPATH_PRESENT(pEA) ((pEA)->ADsPath_present = 1)
  833. #define ADSPATH_ABSENT(pEA) ((pEA)->ADsPath_present = 0)
  834. #define IS_STOREGETTYPE_PRESENT(pEA) ((pEA)->StoreGetType_present)
  835. #define IS_STOREGETTYPE_ABSENT(pEA) (!((pEA)->StoreGetType_present))
  836. #define STOREGETTYPE_PRESENT(pEA) ((pEA)->StoreGetType_present = 1)
  837. #define STOREGETTYPE_ABSENT(pEA) ((pEA)->StoreGetType_present = 0)
  838. #define IS_FLAGS1_PRESENT(pEA) ((pEA)->Flags1_present)
  839. #define IS_FLAGS1_ABSENT(pEA) (!((pEA)->Flags1_present))
  840. #define FLAGS1_PRESENT(pEA) ((pEA)->Flags1_present = 1)
  841. #define FLAGS1_ABSENT(pEA) ((pEA)->Flags1_present = 0)
  842. #define IS_FLAGS2_PRESENT(pEA) ((pEA)->Flags2_present)
  843. #define IS_FLAGS2_ABSENT(pEA) (!((pEA)->Flags2_present))
  844. #define FLAGS2_PRESENT(pEA) ((pEA)->Flags2_present = 1)
  845. #define FLAGS2_ABSENT(pEA) ((pEA)->Flags2_present = 0)
  846. #define IS_DWORD1_PRESENT(pEA) ((pEA)->Dword1_present)
  847. #define IS_DWORD1_ABSENT(pEA) (!((pEA)->Dword1_present))
  848. #define DWORD1_PRESENT(pEA) ((pEA)->Dword1_present = 1)
  849. #define DWORD1_ABSENT(pEA) ((pEA)->Dword1_present = 0)
  850. #define IS_DWORD2_PRESENT(pEA) ((pEA)->Dword2_present)
  851. #define IS_DWORD2_ABSENT(pEA) (!((pEA)->Dword2_present))
  852. #define DWORD2_PRESENT(pEA) ((pEA)->Dword2_present = 1)
  853. #define DWORD2_ABSENT(pEA) ((pEA)->Dword2_present = 0)
  854. #define IS_STRING1_PRESENT(pEA) ((pEA)->String1_present)
  855. #define IS_STRING1_ABSENT(pEA) (!((pEA)->String1_present))
  856. #define STRING1_PRESENT(pEA) ((pEA)->String1_present = 1)
  857. #define STRING1_ABSENT(pEA) ((pEA)->String1_present = 0)
  858. #define IS_STRING2_PRESENT(pEA) ((pEA)->String2_present)
  859. #define IS_STRING2_ABSENT(pEA) (!((pEA)->String2_present))
  860. #define STRING2_PRESENT(pEA) ((pEA)->String2_present = 1)
  861. #define STRING2_ABSENT(pEA) ((pEA)->String2_present = 0)
  862. #define IS_STRING3_PRESENT(pEA) ((pEA)->String3_present)
  863. #define IS_STRING3_ABSENT(pEA) (!((pEA)->String3_present))
  864. #define STRING3_PRESENT(pEA) ((pEA)->String3_present = 1)
  865. #define STRING3_ABSENT(pEA) ((pEA)->String3_present = 0)
  866. #define IS_STRING4_PRESENT(pEA) ((pEA)->String4_present)
  867. #define IS_STRING4_ABSENT(pEA) (!((pEA)->String4_present))
  868. #define STRING4_PRESENT(pEA) ((pEA)->String4_present = 1)
  869. #define STRING4_ABSENT(pEA) ((pEA)->String4_present = 0)
  870. #define IS_BINARY1_PRESENT(pEA) ((pEA)->Binary1_present)
  871. #define IS_BINARY1_ABSENT(pEA) (!((pEA)->Binary1_present))
  872. #define BINARY1_PRESENT(pEA) ((pEA)->Binary1_present = 1)
  873. #define BINARY1_ABSENT(pEA) ((pEA)->Binary1_present = 0)
  874. #define IS_BINARY2_PRESENT(pEA) ((pEA)->Binary2_present)
  875. #define IS_BINARY2_ABSENT(pEA) (!((pEA)->Binary2_present))
  876. #define BINARY2_PRESENT(pEA) ((pEA)->Binary2_present = 1)
  877. #define BINARY2_ABSENT(pEA) ((pEA)->Binary2_present = 0)
  878. //EndExport(defines)
  879. //BeginExport(inline)
  880. BOOL _inline
  881. IsAnythingPresent(
  882. IN PEATTRIB pEA
  883. )
  884. {
  885. return IS_ADDRESS1_PRESENT(pEA)
  886. || IS_ADDRESS2_PRESENT(pEA)
  887. || IS_ADDRESS3_PRESENT(pEA)
  888. || IS_ADSPATH_PRESENT(pEA)
  889. || IS_STOREGETTYPE_PRESENT(pEA)
  890. || IS_FLAGS1_PRESENT(pEA)
  891. || IS_FLAGS2_PRESENT(pEA)
  892. || IS_DWORD1_PRESENT(pEA)
  893. || IS_DWORD2_PRESENT(pEA)
  894. || IS_STRING1_PRESENT(pEA)
  895. || IS_STRING2_PRESENT(pEA)
  896. || IS_STRING3_PRESENT(pEA)
  897. || IS_STRING4_PRESENT(pEA)
  898. || IS_BINARY1_PRESENT(pEA)
  899. || IS_BINARY2_PRESENT(pEA)
  900. ;
  901. }
  902. //EndExport(inline)
  903. //BeginExport(inline)
  904. BOOL _inline
  905. IsEverythingPresent(
  906. IN PEATTRIB pEA
  907. )
  908. {
  909. return IS_ADDRESS1_PRESENT(pEA)
  910. && IS_ADDRESS2_PRESENT(pEA)
  911. && IS_ADDRESS3_PRESENT(pEA)
  912. && IS_ADSPATH_PRESENT(pEA)
  913. && IS_STOREGETTYPE_PRESENT(pEA)
  914. && IS_FLAGS1_PRESENT(pEA)
  915. && IS_FLAGS2_PRESENT(pEA)
  916. && IS_DWORD1_PRESENT(pEA)
  917. && IS_DWORD2_PRESENT(pEA)
  918. && IS_STRING1_PRESENT(pEA)
  919. && IS_STRING2_PRESENT(pEA)
  920. && IS_STRING3_PRESENT(pEA)
  921. && IS_STRING4_PRESENT(pEA)
  922. && IS_BINARY1_PRESENT(pEA)
  923. && IS_BINARY2_PRESENT(pEA)
  924. ;
  925. }
  926. //EndExport(inline)
  927. //BeginExport(inline)
  928. VOID _inline
  929. EverythingPresent(
  930. IN PEATTRIB pEA
  931. )
  932. {
  933. ADDRESS1_PRESENT(pEA);
  934. ADDRESS2_PRESENT(pEA);
  935. ADDRESS3_PRESENT(pEA);
  936. ADSPATH_PRESENT(pEA);
  937. STOREGETTYPE_ABSENT(pEA);
  938. FLAGS1_PRESENT(pEA);
  939. FLAGS2_PRESENT(pEA);
  940. DWORD1_PRESENT(pEA);
  941. DWORD2_PRESENT(pEA);
  942. STRING1_PRESENT(pEA);
  943. STRING2_PRESENT(pEA);
  944. STRING3_PRESENT(pEA);
  945. STRING4_PRESENT(pEA);
  946. BINARY1_PRESENT(pEA);
  947. BINARY2_PRESENT(pEA);
  948. }
  949. //EndExport(inline)
  950. //BeginExport(inline)
  951. VOID _inline
  952. NothingPresent(
  953. IN PEATTRIB pEA
  954. )
  955. {
  956. ADDRESS1_ABSENT(pEA);
  957. ADDRESS2_ABSENT(pEA);
  958. ADDRESS3_ABSENT(pEA);
  959. ADSPATH_ABSENT(pEA);
  960. STOREGETTYPE_ABSENT(pEA);
  961. FLAGS1_ABSENT(pEA);
  962. FLAGS2_ABSENT(pEA);
  963. DWORD1_ABSENT(pEA);
  964. DWORD2_ABSENT(pEA);
  965. STRING1_ABSENT(pEA);
  966. STRING2_ABSENT(pEA);
  967. STRING3_ABSENT(pEA);
  968. STRING4_ABSENT(pEA);
  969. BINARY1_ABSENT(pEA);
  970. BINARY2_ABSENT(pEA);
  971. }
  972. //EndExport(inline)
  973. const char
  974. ch_Address1 = L'i' ,
  975. ch_Address2 = L'j' ,
  976. ch_Address3 = L'k' ,
  977. ch_ADsPath_relative = L'r' ,
  978. ch_ADsPath_absolute = L'p' ,
  979. ch_ADsPath_diff_srvr = L'l' ,
  980. ch_Flags1 = L'f' ,
  981. ch_Flags2 = L'g' ,
  982. ch_Dword1 = L'd' ,
  983. ch_Dword2 = L'e' ,
  984. ch_String1 = L's' ,
  985. ch_String2 = L't' ,
  986. ch_String3 = L'u' ,
  987. ch_String4 = L'v' ,
  988. ch_Binary1 = L'b' ,
  989. ch_Binary2 = L'c' ,
  990. ch_FieldSep = L'$' ;
  991. DWORD
  992. StringToIpAddress( // convert a string to an ip-address
  993. IN LPWSTR String,
  994. IN OUT DWORD *Address
  995. )
  996. {
  997. CHAR Buffer[20]; // large enough to hold any ip address stuff
  998. DWORD Count;
  999. LPSTR SkippedWhiteSpace;
  1000. Count = wcstombs(Buffer, String, sizeof(Buffer) - 1); // save space for '\0'
  1001. if( -1 == Count ) return ERROR_INVALID_DATA;
  1002. Buffer[Count] = '\0';
  1003. SkippedWhiteSpace = Buffer;
  1004. while(( ' ' == *SkippedWhiteSpace || '\t' == *SkippedWhiteSpace) &&
  1005. ( SkippedWhiteSpace < &Buffer[Count])) {
  1006. SkippedWhiteSpace++;
  1007. }
  1008. *Address= ntohl(inet_addr(SkippedWhiteSpace));// address is in host order..
  1009. if( '\0' == *SkippedWhiteSpace ) return ERROR_INVALID_DATA;
  1010. return Count <= sizeof("000.000.000.000") ? ERROR_SUCCESS : ERROR_INVALID_DATA;
  1011. }
  1012. DWORD _inline
  1013. StringToFlags( // convert a string to a DWORD
  1014. IN LPWSTR String,
  1015. IN OUT DWORD *Flags
  1016. )
  1017. {
  1018. DWORD Count;
  1019. LPWSTR Remaining;
  1020. *Flags = ntohl(wcstoul(String, &Remaining,0));// see input for # base. conv to host order
  1021. if( *Remaining == L'\0' ) return ERROR_SUCCESS;
  1022. return ERROR_INVALID_DATA;
  1023. }
  1024. BYTE _inline
  1025. Hex(
  1026. IN WCHAR wCh
  1027. )
  1028. {
  1029. if( wCh >= '0' && wCh <= '9' ) return wCh - '0';
  1030. if( wCh >= 'A' && wCh <= 'F' ) return wCh - 'A' + 10;
  1031. if( wCh >= 'a' && wCh <= 'f' ) return wCh - 'a' + 10;
  1032. return 0x0F+1; // this means error!!!
  1033. }
  1034. DWORD _inline
  1035. StringToBinary( // inline conversion of a string to binary
  1036. IN OUT LPWSTR String, // this string is mangled while converting
  1037. IN OUT LPBYTE *Bytes, // this ptr is set to some memory in String..
  1038. IN OUT DWORD *nBytes // # of hex bytes copied into location Bytes
  1039. ) {
  1040. LPBYTE HexString;
  1041. DWORD n;
  1042. BYTE ch1, ch2;
  1043. HexString = *Bytes = (LPBYTE)String;
  1044. n = 0;
  1045. while( *String != L'\0' ) { // look at each character
  1046. ch1 = Hex(*String++);
  1047. ch2 = Hex(*String++);
  1048. if( ch1 > 0xF || ch2 > 0xF ) { // invalid hex bytes for input?
  1049. return ERROR_INVALID_DATA;
  1050. }
  1051. *HexString ++ = (ch1 << 4 ) | ch2;
  1052. n ++;
  1053. }
  1054. *nBytes = n;
  1055. return ERROR_SUCCESS;
  1056. }
  1057. DWORD
  1058. ConvertStringtoEAttrib( // parse and get the fields out
  1059. IN OUT LPWSTR String, // may be destroyed in the process
  1060. IN OUT PEATTRIB Attrib // fill this in
  1061. )
  1062. {
  1063. DWORD Result;
  1064. DWORD Address;
  1065. DWORD Flags;
  1066. WCHAR ThisChar;
  1067. LPWSTR ThisString;
  1068. CHAR Dummy[20];
  1069. WCHAR Sep;
  1070. Require(Attrib);
  1071. NothingPresent(Attrib);
  1072. if( String ) StoreTrace2("ConvertStringtoEAttrib(%ws) called\n", String);
  1073. Sep = ch_FieldSep;
  1074. while(String && *String && (ThisChar = *String ++)) {
  1075. ThisString = String;
  1076. do { // skip to the next attrib
  1077. String = wcschr(String, Sep);
  1078. if( NULL == String ) break;
  1079. if( String[1] == Sep ) { // double consequtive field-sep's stand for the real thing..
  1080. wcscpy(String, &String[1]); // remove one of the field-separators, and try looking for one lateron.
  1081. String ++;
  1082. continue;
  1083. }
  1084. *String++ = L'\0'; // ok, got a real separator: mark that zero and prepare for next
  1085. break;
  1086. } while(1); // this could as well be while(0) ??
  1087. if( ch_Address1 == ThisChar ) { // this is address1
  1088. SetInternalFormatError(REPEATED_ADDRESS1, IS_ADDRESS1_PRESENT(Attrib));
  1089. Result = StringToIpAddress(
  1090. ThisString,
  1091. &Address
  1092. );
  1093. if( ERROR_SUCCESS != Result ) { // should not happen
  1094. SetInternalFormatError(INVALID_ADDRESS1, TRUE);
  1095. } else {
  1096. ADDRESS1_PRESENT(Attrib);
  1097. Attrib->Address1 = Address;
  1098. StoreTrace2("Found address1 %s\n", inet_ntoa(*(struct in_addr*)&Address));
  1099. }
  1100. continue;
  1101. }
  1102. if( ch_Address2 == ThisChar ) {
  1103. SetInternalFormatError(REPEATED_ADDRESS2, IS_ADDRESS2_PRESENT(Attrib));
  1104. Result = StringToIpAddress(
  1105. ThisString,
  1106. &Address
  1107. );
  1108. if( ERROR_SUCCESS != Result ) { // should not happen
  1109. SetInternalFormatError(INVALID_ADDRESS2, TRUE);
  1110. } else {
  1111. ADDRESS2_PRESENT(Attrib);
  1112. Attrib->Address2 = Address;
  1113. StoreTrace2("Found address2 %s\n", inet_ntoa(*(struct in_addr*)&Address));
  1114. }
  1115. continue;
  1116. }
  1117. if( ch_Address3 == ThisChar ) {
  1118. SetInternalFormatError(REPEATED_ADDRESS3, IS_ADDRESS3_PRESENT(Attrib));
  1119. Result = StringToIpAddress(
  1120. ThisString,
  1121. &Address
  1122. );
  1123. if( ERROR_SUCCESS != Result ) { // should not happen
  1124. SetInternalFormatError(INVALID_ADDRESS3, TRUE);
  1125. } else {
  1126. ADDRESS3_PRESENT(Attrib);
  1127. Attrib->Address3 = Address;
  1128. StoreTrace2("Found address3 %s\n", inet_ntoa(*(struct in_addr*)&Address));
  1129. }
  1130. continue;
  1131. }
  1132. if( ch_ADsPath_relative == ThisChar ||
  1133. ch_ADsPath_absolute == ThisChar ||
  1134. ch_ADsPath_diff_srvr == ThisChar ) {
  1135. SetInternalFormatError(REPEATED_ADSPATH, IS_ADSPATH_PRESENT(Attrib));
  1136. ADSPATH_PRESENT(Attrib);
  1137. STOREGETTYPE_PRESENT(Attrib);
  1138. Attrib->ADsPath = ThisString;
  1139. if( ch_ADsPath_relative == ThisChar )
  1140. Attrib->StoreGetType = StoreGetChildType;
  1141. else if(ch_ADsPath_absolute == ThisChar )
  1142. Attrib->StoreGetType = StoreGetAbsoluteSameServerType;
  1143. else if(ch_ADsPath_diff_srvr == ThisChar )
  1144. Attrib->StoreGetType = StoreGetAbsoluteOtherServerType;
  1145. StoreTrace3("Found path [%ld] [%ws]\n", Attrib->StoreGetType, ThisString);
  1146. continue;
  1147. }
  1148. if( ch_String1 == ThisChar ) {
  1149. SetInternalFormatError(REPEATED_STRING1, IS_STRING1_PRESENT(Attrib));
  1150. STRING1_PRESENT(Attrib);
  1151. Attrib->String1 = ThisString;
  1152. StoreTrace2("Found string1 [%ws]\n", ThisString);
  1153. continue;
  1154. }
  1155. if( ch_String2 == ThisChar ) {
  1156. SetInternalFormatError(REPEATED_STRING2, IS_STRING2_PRESENT(Attrib));
  1157. STRING2_PRESENT(Attrib);
  1158. Attrib->String2 = ThisString;
  1159. StoreTrace2("Found string2 [%ws]\n", ThisString);
  1160. continue;
  1161. }
  1162. if( ch_String3 == ThisChar ) {
  1163. SetInternalFormatError(REPEATED_STRING3, IS_STRING3_PRESENT(Attrib));
  1164. STRING3_PRESENT(Attrib);
  1165. Attrib->String3 = ThisString;
  1166. StoreTrace2("Found string3 [%ws]\n", ThisString);
  1167. continue;
  1168. }
  1169. if( ch_String4 == ThisChar ) {
  1170. SetInternalFormatError(REPEATED_STRING4, IS_STRING4_PRESENT(Attrib));
  1171. STRING4_PRESENT(Attrib);
  1172. Attrib->String4 = ThisString;
  1173. StoreTrace2("Found string4 [%ws]\n", ThisString);
  1174. continue;
  1175. }
  1176. if( ch_Flags1 == ThisChar ) {
  1177. SetInternalFormatError(REPEATED_FLAGS1, IS_FLAGS1_PRESENT(Attrib));
  1178. Result = StringToFlags(
  1179. ThisString,
  1180. &Flags
  1181. );
  1182. if( ERROR_SUCCESS != Result ) {
  1183. SetInternalFormatError(INVALID_FLAGS1, TRUE);
  1184. } else {
  1185. FLAGS1_PRESENT(Attrib);
  1186. Attrib->Flags1 = Flags;
  1187. StoreTrace2("Found flags1: 0x%lx\n", Flags);
  1188. }
  1189. continue;
  1190. }
  1191. if( ch_Flags2 == ThisChar ) {
  1192. SetInternalFormatError(REPEATED_FLAGS2, IS_FLAGS2_PRESENT(Attrib));
  1193. Result = StringToFlags(
  1194. ThisString,
  1195. &Flags
  1196. );
  1197. if( ERROR_SUCCESS != Result ) {
  1198. SetInternalFormatError(INVALID_FLAGS2, TRUE);
  1199. } else {
  1200. FLAGS2_PRESENT(Attrib);
  1201. Attrib->Flags2 = Flags;
  1202. StoreTrace2("Found flags2: 0x%lx\n", Flags);
  1203. }
  1204. continue;
  1205. }
  1206. if( ch_Dword1 == ThisChar ) {
  1207. SetInternalFormatError(REPEATED_DWORD1, IS_DWORD1_PRESENT(Attrib));
  1208. Result = StringToFlags(
  1209. ThisString,
  1210. &Flags
  1211. );
  1212. if( ERROR_SUCCESS != Result ) {
  1213. SetInternalFormatError(INVALID_DWORD1, TRUE);
  1214. } else {
  1215. DWORD1_PRESENT(Attrib);
  1216. Attrib->Dword1 = Flags;
  1217. StoreTrace2("Found dword1: 0x%lx\n", Flags);
  1218. }
  1219. continue;
  1220. }
  1221. if( ch_Dword2 == ThisChar ) {
  1222. SetInternalFormatError(REPEATED_DWORD2, IS_DWORD2_PRESENT(Attrib));
  1223. Result = StringToFlags(
  1224. ThisString,
  1225. &Flags
  1226. );
  1227. if( ERROR_SUCCESS != Result ) {
  1228. SetInternalFormatError(INVALID_DWORD2, TRUE);
  1229. } else {
  1230. DWORD2_PRESENT(Attrib);
  1231. Attrib->Dword2 = Flags;
  1232. StoreTrace2("Found dword2: 0x%lx\n", Flags);
  1233. }
  1234. continue;
  1235. }
  1236. if( ch_Binary1 == ThisChar ) {
  1237. SetInternalFormatError(REPEATED_BINARY1, IS_BINARY1_PRESENT(Attrib));
  1238. Result = StringToBinary(
  1239. ThisString,
  1240. &Attrib->Binary1,
  1241. &Attrib->BinLen1
  1242. );
  1243. if( ERROR_SUCCESS != Result ) {
  1244. SetInternalFormatError(INVALID_BINARY1, TRUE);
  1245. BINARY1_ABSENT(Attrib);
  1246. } else {
  1247. BINARY1_PRESENT(Attrib);
  1248. StoreTrace2("Found Binary1 of length %ld\n", Attrib->BinLen1);
  1249. }
  1250. continue;
  1251. }
  1252. if( ch_Binary2 == ThisChar ) {
  1253. SetInternalFormatError(REPEATED_BINARY2, IS_BINARY2_PRESENT(Attrib));
  1254. Result = StringToBinary(
  1255. ThisString,
  1256. &Attrib->Binary2,
  1257. &Attrib->BinLen2
  1258. );
  1259. if( ERROR_SUCCESS != Result ) {
  1260. SetInternalFormatError(INVALID_BINARY2, TRUE);
  1261. BINARY2_ABSENT(Attrib);
  1262. } else {
  1263. BINARY2_PRESENT(Attrib);
  1264. StoreTrace2("Found Binary2 of length %ld\n", Attrib->BinLen2);
  1265. }
  1266. continue;
  1267. }
  1268. SetInternalFormatError(INVALID_ATTRIB_FIELD, TRUE);
  1269. }
  1270. return IsAnythingPresent(Attrib)? ERROR_SUCCESS : ERROR_INVALID_DATA;
  1271. }
  1272. BOOL _inline
  1273. InvalidStringInBinary( // check if the given binary stream forms a LPWSTR
  1274. IN LPBYTE Data,
  1275. IN DWORD DataLen
  1276. )
  1277. {
  1278. if( 0 == DataLen ) return TRUE;
  1279. if( DataLen % sizeof(WCHAR) ) return TRUE;
  1280. DataLen /= sizeof(WCHAR);
  1281. if( L'\0' != ((LPWSTR)Data)[DataLen-1] ) return TRUE;
  1282. return FALSE;
  1283. }
  1284. DWORD
  1285. ConvertBinarytoEAttrib( // parse and get the fields out
  1286. IN OUT LPBYTE Data, // input free format data
  1287. IN DWORD DataLen, // bytes for data length
  1288. IN OUT PEATTRIB Attrib // fill this in
  1289. )
  1290. {
  1291. DWORD Result;
  1292. DWORD Address;
  1293. DWORD Flags;
  1294. DWORD Offset;
  1295. DWORD ThisDataLen;
  1296. DWORD xDataLen;
  1297. LPBYTE xData;
  1298. LPBYTE ThisData;
  1299. WCHAR ThisChar;
  1300. CHAR Dummy[20];
  1301. Require(Attrib);
  1302. NothingPresent(Attrib);
  1303. Offset = 0;
  1304. while( Data && DataLen >= sizeof(BYTE) + sizeof(WORD) ) {
  1305. ThisChar = ntohs(*(LPWORD)Data);
  1306. Data += sizeof(WORD); DataLen -= sizeof(WORD);
  1307. ThisDataLen = ntohs(*(LPWORD)Data);
  1308. Data += sizeof(WORD); DataLen -= sizeof(WORD);
  1309. if( ROUND_UP_COUNT(ThisDataLen, ALIGN_WORD) > DataLen ) {
  1310. SetInternalFormatError(INVALID_BINARY_CODING, TRUE);
  1311. break;
  1312. }
  1313. ThisData = Data;
  1314. Data += ROUND_UP_COUNT(ThisDataLen, ALIGN_WORD);
  1315. DataLen -= ROUND_UP_COUNT(ThisDataLen, ALIGN_WORD);
  1316. if( ch_Address1 == ThisChar ) { // this is address1
  1317. SetInternalFormatError(REPEATED_ADDRESS1, IS_ADDRESS1_PRESENT(Attrib));
  1318. if( sizeof(DWORD) != ThisDataLen ) {
  1319. SetInternalFormatError(INVALID_ADDRESS1, TRUE);
  1320. } else {
  1321. Address = ntohl(*(DWORD UNALIGNED *)ThisData);
  1322. ADDRESS1_PRESENT(Attrib);
  1323. Attrib->Address1 = Address;
  1324. StoreTrace2("Found address1 %s\n", inet_ntoa(*(struct in_addr*)&Address));
  1325. }
  1326. continue;
  1327. }
  1328. if( ch_Address2 == ThisChar ) {
  1329. SetInternalFormatError(REPEATED_ADDRESS2, IS_ADDRESS2_PRESENT(Attrib));
  1330. if( sizeof(DWORD) != ThisDataLen ) {
  1331. SetInternalFormatError(INVALID_ADDRESS2, TRUE);
  1332. } else {
  1333. Address = ntohl(*(DWORD UNALIGNED *)ThisData);
  1334. ADDRESS2_PRESENT(Attrib);
  1335. Attrib->Address2 = Address;
  1336. StoreTrace2("Found address2 %s\n", inet_ntoa(*(struct in_addr*)&Address));
  1337. }
  1338. continue;
  1339. }
  1340. if( ch_Address3 == ThisChar ) {
  1341. SetInternalFormatError(REPEATED_ADDRESS3, IS_ADDRESS3_PRESENT(Attrib));
  1342. if( sizeof(DWORD) != ThisDataLen ) {
  1343. SetInternalFormatError(INVALID_ADDRESS3, TRUE);
  1344. } else {
  1345. Address = ntohl(*(DWORD UNALIGNED *)ThisData);
  1346. ADDRESS3_PRESENT(Attrib);
  1347. Attrib->Address3 = Address;
  1348. StoreTrace2("Found address3 %s\n", inet_ntoa(*(struct in_addr*)&Address));
  1349. }
  1350. continue;
  1351. }
  1352. if( ch_ADsPath_relative == ThisChar ||
  1353. ch_ADsPath_absolute == ThisChar ||
  1354. ch_ADsPath_diff_srvr == ThisChar ) {
  1355. SetInternalFormatError(REPEATED_ADSPATH, IS_ADSPATH_PRESENT(Attrib));
  1356. if( InvalidStringInBinary(ThisData, ThisDataLen) ) {
  1357. SetInternalFormatError(INVALID_ADSPATH, TRUE);
  1358. continue;
  1359. }
  1360. ADSPATH_PRESENT(Attrib);
  1361. STOREGETTYPE_PRESENT(Attrib);
  1362. Attrib->ADsPath = (LPWSTR)ThisData;
  1363. if( ch_ADsPath_relative == ThisChar )
  1364. Attrib->StoreGetType = StoreGetChildType;
  1365. else if(ch_ADsPath_absolute == ThisChar )
  1366. Attrib->StoreGetType = StoreGetAbsoluteSameServerType;
  1367. else if(ch_ADsPath_diff_srvr == ThisChar )
  1368. Attrib->StoreGetType = StoreGetAbsoluteOtherServerType;
  1369. StoreTrace3("Found path [%ld] [%ws]\n", Attrib->StoreGetType, (LPWSTR)ThisData);
  1370. continue;
  1371. }
  1372. if( ch_String1 == ThisChar ) {
  1373. SetInternalFormatError(REPEATED_STRING1, IS_STRING1_PRESENT(Attrib));
  1374. if( InvalidStringInBinary(ThisData, ThisDataLen) ) {
  1375. SetInternalFormatError(INVALID_STRING1, TRUE);
  1376. continue;
  1377. }
  1378. STRING1_PRESENT(Attrib);
  1379. Attrib->String1 = (LPWSTR)ThisData;
  1380. StoreTrace2("Found string1 [%ws]\n", (LPWSTR)ThisData);
  1381. continue;
  1382. }
  1383. if( ch_String2 == ThisChar ) {
  1384. SetInternalFormatError(REPEATED_STRING2, IS_STRING2_PRESENT(Attrib));
  1385. if( InvalidStringInBinary(ThisData, ThisDataLen) ) {
  1386. SetInternalFormatError(INVALID_STRING2, TRUE);
  1387. continue;
  1388. }
  1389. STRING2_PRESENT(Attrib);
  1390. Attrib->String2 = (LPWSTR)ThisData;
  1391. StoreTrace2("Found string2 [%ws]\n", (LPWSTR)ThisData);
  1392. continue;
  1393. }
  1394. if( ch_String3 == ThisChar ) {
  1395. SetInternalFormatError(REPEATED_STRING3, IS_STRING3_PRESENT(Attrib));
  1396. if( InvalidStringInBinary(ThisData, ThisDataLen) ) {
  1397. SetInternalFormatError(INVALID_STRING3, TRUE);
  1398. continue;
  1399. }
  1400. STRING3_PRESENT(Attrib);
  1401. Attrib->String3 = (LPWSTR)ThisData;
  1402. StoreTrace2("Found string3 [%ws]\n", (LPWSTR)ThisData);
  1403. continue;
  1404. }
  1405. if( ch_String4 == ThisChar ) {
  1406. SetInternalFormatError(REPEATED_STRING4, IS_STRING4_PRESENT(Attrib));
  1407. if( InvalidStringInBinary(ThisData, ThisDataLen) ) {
  1408. SetInternalFormatError(INVALID_STRING4, TRUE);
  1409. continue;
  1410. }
  1411. STRING4_PRESENT(Attrib);
  1412. Attrib->String4 = (LPWSTR)ThisData;
  1413. StoreTrace2("Found string4 [%ws]\n", (LPWSTR)ThisData);
  1414. continue;
  1415. }
  1416. if( ch_Flags1 == ThisChar ) {
  1417. SetInternalFormatError(REPEATED_FLAGS1, IS_FLAGS1_PRESENT(Attrib));
  1418. if( sizeof(DWORD) != ThisDataLen ) {
  1419. SetInternalFormatError(INVALID_FLAGS1, TRUE);
  1420. } else {
  1421. Flags = ntohl(*(DWORD UNALIGNED *)ThisData);
  1422. FLAGS1_PRESENT(Attrib);
  1423. Attrib->Flags1 = Flags;
  1424. StoreTrace2("Found flags1: 0x%lx\n", Flags);
  1425. }
  1426. continue;
  1427. }
  1428. if( ch_Flags2 == ThisChar ) {
  1429. SetInternalFormatError(REPEATED_FLAGS2, IS_FLAGS2_PRESENT(Attrib));
  1430. if( sizeof(DWORD) != ThisDataLen ) {
  1431. SetInternalFormatError(INVALID_FLAGS2, TRUE);
  1432. } else {
  1433. Flags = ntohl(*(DWORD UNALIGNED *)ThisData);
  1434. FLAGS2_PRESENT(Attrib);
  1435. Attrib->Flags2 = Flags;
  1436. StoreTrace2("Found flags2: 0x%lx\n", Flags);
  1437. }
  1438. continue;
  1439. }
  1440. if( ch_Dword1 == ThisChar ) {
  1441. SetInternalFormatError(REPEATED_DWORD1, IS_DWORD1_PRESENT(Attrib));
  1442. if( sizeof(DWORD) != ThisDataLen ) {
  1443. SetInternalFormatError(INVALID_DWORD1, TRUE);
  1444. } else {
  1445. Flags = ntohl(*(DWORD UNALIGNED *)ThisData);
  1446. DWORD1_PRESENT(Attrib);
  1447. Attrib->Dword1 = Flags;
  1448. StoreTrace2("Found dword1: 0x%lx\n", Flags);
  1449. }
  1450. continue;
  1451. }
  1452. if( ch_Dword2 == ThisChar ) {
  1453. SetInternalFormatError(REPEATED_DWORD2, IS_DWORD2_PRESENT(Attrib));
  1454. if( sizeof(DWORD) != ThisDataLen ) {
  1455. SetInternalFormatError(INVALID_DWORD2, TRUE);
  1456. } else {
  1457. Flags = ntohl(*(DWORD UNALIGNED *)ThisData);
  1458. DWORD2_PRESENT(Attrib);
  1459. Attrib->Dword2 = Flags;
  1460. StoreTrace2("Found dword2: 0x%lx\n", Flags);
  1461. }
  1462. continue;
  1463. }
  1464. if( ch_Binary1 == ThisChar ) {
  1465. SetInternalFormatError(REPEATED_BINARY1, IS_BINARY1_PRESENT(Attrib));
  1466. BINARY1_PRESENT(Attrib);
  1467. Attrib->Binary1 = ThisData;
  1468. Attrib->BinLen1 = ThisDataLen;
  1469. StoreTrace2("Found %ld bytes of binary 1 data\n", ThisDataLen);
  1470. continue;
  1471. }
  1472. if( ch_Binary2 == ThisChar ) {
  1473. SetInternalFormatError(REPEATED_BINARY2, IS_BINARY2_PRESENT(Attrib));
  1474. BINARY2_PRESENT(Attrib);
  1475. Attrib->Binary2 = ThisData;
  1476. Attrib->BinLen2 = ThisDataLen;
  1477. StoreTrace2("Found %ld bytes of binary 2 data\n", ThisDataLen);
  1478. continue;
  1479. }
  1480. SetInternalFormatError(INVALID_ATTRIB_FIELD, TRUE);
  1481. }
  1482. return IsAnythingPresent(Attrib) ? ERROR_SUCCESS: ERROR_INVALID_DATA;
  1483. }
  1484. PEATTRIB
  1485. CloneAttrib(
  1486. IN PEATTRIB Attrib
  1487. )
  1488. {
  1489. PEATTRIB RetVal;
  1490. DWORD Size;
  1491. Size = sizeof(*Attrib);
  1492. Size = ROUND_UP_COUNT(Size, ALIGN_WORST);
  1493. if( IS_ADSPATH_PRESENT(Attrib) ) {
  1494. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->ADsPath));
  1495. }
  1496. if( IS_STRING1_PRESENT(Attrib) ) {
  1497. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String1));
  1498. }
  1499. if( IS_STRING2_PRESENT(Attrib) ) {
  1500. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String2));
  1501. }
  1502. if( IS_STRING3_PRESENT(Attrib) ) {
  1503. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String3));
  1504. }
  1505. if( IS_STRING4_PRESENT(Attrib) ) {
  1506. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String4));
  1507. }
  1508. if( IS_BINARY1_PRESENT(Attrib) ) Size += Attrib->BinLen1;
  1509. if( IS_BINARY2_PRESENT(Attrib) ) Size += Attrib->BinLen2;
  1510. RetVal = (PEATTRIB)MemAlloc(Size);
  1511. if( NULL == RetVal ) return NULL;
  1512. Size = sizeof(*Attrib);
  1513. Size = ROUND_UP_COUNT(Size, ALIGN_WORST);
  1514. *RetVal = *Attrib;
  1515. if( IS_ADSPATH_PRESENT(Attrib) ) {
  1516. RetVal->ADsPath = (LPWSTR)(Size + (LPBYTE)RetVal);
  1517. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->ADsPath));
  1518. wcscpy(RetVal->ADsPath, Attrib->ADsPath);
  1519. }
  1520. if( IS_STRING1_PRESENT(Attrib) ) {
  1521. RetVal->String1 = (LPWSTR)(Size + (LPBYTE)RetVal);
  1522. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String1));
  1523. wcscpy(RetVal->String1, Attrib->String1);
  1524. }
  1525. if( IS_STRING2_PRESENT(Attrib) ) {
  1526. RetVal->String2 = (LPWSTR)(Size + (LPBYTE)RetVal);
  1527. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String2));
  1528. wcscpy(RetVal->String2, Attrib->String2);
  1529. }
  1530. if( IS_STRING3_PRESENT(Attrib) ) {
  1531. RetVal->String3 = (LPWSTR)(Size + (LPBYTE)RetVal);
  1532. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String3));
  1533. wcscpy(RetVal->String3, Attrib->String3);
  1534. }
  1535. if( IS_STRING4_PRESENT(Attrib) ) {
  1536. RetVal->String4 = (LPWSTR)(Size + (LPBYTE)RetVal);
  1537. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String4));
  1538. wcscpy(RetVal->String4, Attrib->String4);
  1539. }
  1540. if( IS_BINARY1_PRESENT(Attrib) ) {
  1541. RetVal->Binary1 = (Size + (LPBYTE)RetVal);
  1542. Size += Attrib->BinLen1;
  1543. memcpy(RetVal->Binary1, Attrib->Binary1, Attrib->BinLen1);
  1544. }
  1545. if( IS_BINARY2_PRESENT(Attrib) ) {
  1546. RetVal->Binary2 = (Size + (LPBYTE)RetVal);
  1547. Size += Attrib->BinLen2;
  1548. memcpy(RetVal->Binary2, Attrib->Binary2, Attrib->BinLen2);
  1549. }
  1550. return RetVal;
  1551. }
  1552. DWORD
  1553. AddAttribToArray(
  1554. IN OUT PARRAY Array,
  1555. IN PEATTRIB Attrib
  1556. )
  1557. {
  1558. DWORD Result;
  1559. Require(Attrib);
  1560. Attrib = CloneAttrib(Attrib);
  1561. if( NULL == Attrib) return ERROR_NOT_ENOUGH_MEMORY;
  1562. Result = MemArrayAddElement(Array, (LPVOID)Attrib);
  1563. if( ERROR_SUCCESS == Result ) return ERROR_SUCCESS;
  1564. MemFree(Attrib);
  1565. return Result;
  1566. }
  1567. BOOL _inline
  1568. OnlyADsPathPresent(
  1569. IN PEATTRIB pEA
  1570. )
  1571. {
  1572. if( ! IS_ADSPATH_PRESENT(pEA) ) return FALSE;
  1573. return IS_ADDRESS1_ABSENT(pEA)
  1574. && IS_ADDRESS2_ABSENT(pEA)
  1575. && IS_ADSPATH_ABSENT(pEA)
  1576. && IS_STOREGETTYPE_ABSENT(pEA)
  1577. && IS_FLAGS1_ABSENT(pEA)
  1578. && IS_FLAGS2_ABSENT(pEA)
  1579. && IS_STRING1_ABSENT(pEA)
  1580. && IS_STRING2_ABSENT(pEA)
  1581. && IS_BINARY1_ABSENT(pEA)
  1582. && IS_BINARY2_ABSENT(pEA)
  1583. ;
  1584. }
  1585. DWORD
  1586. StoreCollectAttributes( // fwd declaration
  1587. IN OUT PSTORE_HANDLE hStore,
  1588. IN DWORD Reserved,
  1589. IN LPWSTR AttribName,
  1590. IN OUT PARRAY ArrayToAddTo,
  1591. IN DWORD RecursionDepth
  1592. );
  1593. DWORD _inline
  1594. StoreCollectAttributesInternal(
  1595. IN OUT PSTORE_HANDLE hStore,
  1596. IN DWORD Reserved,
  1597. IN PEATTRIB Attrib,
  1598. IN LPWSTR AttribName,
  1599. IN OUT PARRAY ArrayToAddTo, // array of PEATTRIBs
  1600. IN DWORD RecursionDepth // 0 ==> no recursion
  1601. )
  1602. {
  1603. DWORD Result, Result2;
  1604. STORE_HANDLE hStore2;
  1605. if( 0 == RecursionDepth ) {
  1606. Result = AddAttribToArray(ArrayToAddTo, Attrib);
  1607. if( ERROR_SUCCESS != Result ) SetInternalFormatError(UNEXPECTED_INTERNAL_ERROR, TRUE);
  1608. return ERROR_STACK_OVERFLOW;
  1609. }
  1610. StoreTrace2("Recursing to %ws\n", Attrib->ADsPath);
  1611. Result = StoreGetHandle(
  1612. hStore,
  1613. /*Reserved*/ 0,
  1614. Attrib->StoreGetType,
  1615. Attrib->ADsPath,
  1616. &hStore2
  1617. );
  1618. if( ERROR_SUCCESS != Result ) return Result;
  1619. Result = StoreCollectAttributes(
  1620. &hStore2,
  1621. Reserved,
  1622. AttribName,
  1623. ArrayToAddTo,
  1624. RecursionDepth-1
  1625. );
  1626. Result2 = StoreCleanupHandle( &hStore2, 0 );
  1627. return Result;
  1628. }
  1629. //BeginExport(function)
  1630. DWORD
  1631. StoreCollectAttributes(
  1632. IN OUT PSTORE_HANDLE hStore,
  1633. IN DWORD Reserved,
  1634. IN LPWSTR AttribName, // this attrib must be some kind of a text string
  1635. IN OUT PARRAY ArrayToAddTo, // array of PEATTRIBs
  1636. IN DWORD RecursionDepth // 0 ==> no recursion
  1637. ) //EndExport(function)
  1638. {
  1639. HRESULT hResult;
  1640. DWORD Result;
  1641. DWORD Error;
  1642. DWORD nAttributes;
  1643. DWORD i;
  1644. PADS_ATTR_INFO Attributes;
  1645. LPWSTR Attribs[1];
  1646. LPWSTR ThisAttribStr;
  1647. EATTRIB ThisEAttrib;
  1648. Attribs[0] = AttribName;
  1649. Attributes = NULL;
  1650. nAttributes = 0;
  1651. hResult = ADSIGetObjectAttributes(
  1652. hStore->ADSIHandle,
  1653. Attribs,
  1654. sizeof(Attribs)/sizeof(Attribs[0]),
  1655. &Attributes,
  1656. &nAttributes
  1657. );
  1658. if( HRESULT_FROM_WIN32( ERROR_DS_NO_ATTRIBUTE_OR_VALUE) == hResult ) {
  1659. return ERROR_SUCCESS;
  1660. }
  1661. if( FAILED(hResult) ) return ConvertHresult(hResult);
  1662. if( 0 == nAttributes || NULL == Attributes )
  1663. return ERROR_SUCCESS;
  1664. Require( 1 == nAttributes );
  1665. Error = ERROR_SUCCESS;
  1666. for( i = 0; i < Attributes[0].dwNumValues ; i ++ ) {
  1667. switch(Attributes[0].pADsValues[i].dwType) {
  1668. case ADSTYPE_DN_STRING:
  1669. ThisAttribStr = Attributes[0].pADsValues[i].DNString; break;
  1670. case ADSTYPE_CASE_EXACT_STRING:
  1671. ThisAttribStr = Attributes[0].pADsValues[i].CaseExactString; break;
  1672. case ADSTYPE_CASE_IGNORE_STRING:
  1673. ThisAttribStr = Attributes[0].pADsValues[i].CaseIgnoreString; break;
  1674. case ADSTYPE_PRINTABLE_STRING:
  1675. ThisAttribStr = Attributes[0].pADsValues[i].PrintableString; break;
  1676. default:
  1677. SetInternalFormatError(UNEXPECTED_COLLECTION_TYPE, TRUE);
  1678. continue;
  1679. }
  1680. Require(ThisAttribStr);
  1681. Result = ConvertStringtoEAttrib(ThisAttribStr, &ThisEAttrib);
  1682. if( ERROR_SUCCESS == Result ) {
  1683. if( OnlyADsPathPresent(&ThisEAttrib) ) {
  1684. Result = StoreCollectAttributesInternal(
  1685. hStore,
  1686. Reserved,
  1687. &ThisEAttrib,
  1688. AttribName,
  1689. ArrayToAddTo,
  1690. RecursionDepth
  1691. );
  1692. } else {
  1693. Result = AddAttribToArray(ArrayToAddTo, &ThisEAttrib);
  1694. }
  1695. if( ERROR_SUCCESS != Result ) Error = Result;
  1696. } else Error = Result;
  1697. }
  1698. FreeADsMem(Attributes);
  1699. return Error;
  1700. }
  1701. DWORD
  1702. StoreCollectBinaryAttributes( // fwd declaration
  1703. IN OUT PSTORE_HANDLE hStore,
  1704. IN DWORD Reserved,
  1705. IN LPWSTR AttribName,
  1706. IN OUT PARRAY ArrayToAddTo,
  1707. IN DWORD RecursionDepth
  1708. );
  1709. DWORD _inline
  1710. StoreCollectBinaryAttributesInternal(
  1711. IN OUT PSTORE_HANDLE hStore,
  1712. IN DWORD Reserved,
  1713. IN PEATTRIB Attrib,
  1714. IN LPWSTR AttribName,
  1715. IN OUT PARRAY ArrayToAddTo, // array of PEATTRIBs
  1716. IN DWORD RecursionDepth // 0 ==> no recursion
  1717. )
  1718. {
  1719. DWORD Result, Result2;
  1720. STORE_HANDLE hStore2;
  1721. if( 0 == RecursionDepth ) {
  1722. Result = AddAttribToArray(ArrayToAddTo, Attrib);
  1723. if( ERROR_SUCCESS != Result ) SetInternalFormatError(UNEXPECTED_INTERNAL_ERROR, TRUE);
  1724. return ERROR_STACK_OVERFLOW;
  1725. }
  1726. StoreTrace2("Recursing to %ws\n", Attrib->ADsPath);
  1727. Result = StoreGetHandle(
  1728. hStore,
  1729. /*Reserved*/ 0,
  1730. Attrib->StoreGetType,
  1731. Attrib->ADsPath,
  1732. &hStore2
  1733. );
  1734. if( ERROR_SUCCESS != Result ) return Result;
  1735. Result = StoreCollectBinaryAttributes(
  1736. &hStore2,
  1737. Reserved,
  1738. AttribName,
  1739. ArrayToAddTo,
  1740. RecursionDepth-1
  1741. );
  1742. Result2 = StoreCleanupHandle( &hStore2, 0 );
  1743. return Result;
  1744. }
  1745. //BeginExport(function)
  1746. DWORD
  1747. StoreCollectBinaryAttributes(
  1748. IN OUT PSTORE_HANDLE hStore,
  1749. IN DWORD Reserved,
  1750. IN LPWSTR AttribName, // accept only attrib type OCTET_STRING
  1751. IN OUT PARRAY ArrayToAddTo, // array of PEATTRIBs
  1752. IN DWORD RecursionDepth // 0 ==> no recursion
  1753. ) //EndExport(function)
  1754. {
  1755. HRESULT hResult;
  1756. DWORD Result;
  1757. DWORD Error;
  1758. DWORD nAttributes;
  1759. DWORD i;
  1760. DWORD DataLength;
  1761. PADS_ATTR_INFO Attributes;
  1762. LPWSTR Attribs[1];
  1763. LPBYTE Data;
  1764. EATTRIB ThisEAttrib;
  1765. Attribs[0] = AttribName;
  1766. Attributes = NULL;
  1767. nAttributes = 0;
  1768. hResult = ADSIGetObjectAttributes(
  1769. hStore->ADSIHandle,
  1770. Attribs,
  1771. sizeof(Attribs)/sizeof(Attribs[0]),
  1772. &Attributes,
  1773. &nAttributes
  1774. );
  1775. if( HRESULT_FROM_WIN32(ERROR_DS_NO_ATTRIBUTE_OR_VALUE) == hResult ) {
  1776. return ERROR_SUCCESS;
  1777. }
  1778. if( FAILED(hResult) ) return ConvertHresult(hResult);
  1779. if( 0 == nAttributes || NULL == Attributes )
  1780. return ERROR_SUCCESS;
  1781. Require( 1 == nAttributes );
  1782. Error = ERROR_SUCCESS;
  1783. for( i = 0; i < Attributes[0].dwNumValues ; i ++ ) {
  1784. if( ADSTYPE_OCTET_STRING != Attributes[0].pADsValues[i].dwType ) {
  1785. SetInternalFormatError(UNEXPECTED_COLLECTION_TYPE, TRUE);
  1786. continue;
  1787. }
  1788. Data = Attributes[0].pADsValues[i].OctetString.lpValue;
  1789. DataLength = Attributes[0].pADsValues[i].OctetString.dwLength;
  1790. Result = ConvertBinarytoEAttrib(Data, DataLength, &ThisEAttrib);
  1791. if( ERROR_SUCCESS == Result ) {
  1792. if( OnlyADsPathPresent(&ThisEAttrib) ) {
  1793. Result = StoreCollectBinaryAttributesInternal(
  1794. hStore,
  1795. Reserved,
  1796. &ThisEAttrib,
  1797. AttribName,
  1798. ArrayToAddTo,
  1799. RecursionDepth
  1800. );
  1801. } else {
  1802. Result = AddAttribToArray(ArrayToAddTo, &ThisEAttrib);
  1803. }
  1804. if( ERROR_SUCCESS != Result ) Error = Result;
  1805. } else Error = Result;
  1806. }
  1807. FreeADsMem(Attributes);
  1808. return Error;
  1809. }
  1810. DWORD _inline
  1811. SizeAfterSeparation( // the field separation character has to doubled.
  1812. IN LPWSTR String, // string with field separation character not escape'ed.
  1813. IN WCHAR Sep
  1814. )
  1815. {
  1816. DWORD RetVal;
  1817. RetVal = wcslen(String);
  1818. while(String = wcschr(String, Sep ) ) {
  1819. RetVal ++;
  1820. }
  1821. return RetVal;
  1822. }
  1823. LPWSTR
  1824. ConvertStringToString( // duplicate any field_sep characters found
  1825. IN LPWSTR InStr,
  1826. IN WCHAR PrefixChar,
  1827. IN LPWSTR Str, // copy into this pre-allocated buffer
  1828. IN WCHAR Sep
  1829. )
  1830. {
  1831. *Str++ = PrefixChar;
  1832. while( *InStr ) {
  1833. if( Sep != *InStr ) {
  1834. *Str ++ = *InStr;
  1835. } else {
  1836. *Str ++ = Sep;
  1837. *Str ++ = Sep;
  1838. }
  1839. InStr ++;
  1840. }
  1841. *Str = L'\0';
  1842. return Str;
  1843. }
  1844. LPWSTR // Return the ptr to where the '\0' is stored
  1845. ConvertAddressToString( // convert ip address to dotted notation LPWSTR
  1846. IN DWORD Address,
  1847. IN WCHAR PrefixChar,
  1848. IN LPWSTR Str // copy into this pre-allocated buffer
  1849. )
  1850. {
  1851. LPSTR AsciiStr;
  1852. Address = htonl(Address); // convert to n/w order before making string..
  1853. *Str ++ = PrefixChar;
  1854. AsciiStr = inet_ntoa(*(struct in_addr *)&Address);
  1855. while( *Str ++ = (WCHAR) *AsciiStr ++ )
  1856. ;
  1857. Str --; *Str = L'\0';
  1858. return Str;
  1859. }
  1860. LPWSTR
  1861. ConvertDwordToString( // convert a DWORD to string in 0x.... fmt
  1862. IN DWORD Dword,
  1863. IN WCHAR PrefixChar,
  1864. IN LPWSTR Str // copy into this pre-allocated buffer
  1865. )
  1866. {
  1867. UCHAR Ch;
  1868. LPWSTR Stream;
  1869. INT i;
  1870. Dword = htonl(Dword); // convert to n/w order before making string.
  1871. *Str ++ = PrefixChar;
  1872. *Str ++ = L'0'; *Str ++ = L'x' ;
  1873. Stream = Str; Str += sizeof(Dword)*2;
  1874. for( i = sizeof(Dword); i ; i -- ) {
  1875. Ch = (BYTE)(Dword & 0x0F);
  1876. Dword >>= 4;
  1877. Stream[i*2 -1] = (Ch < 10)? (L'0'+Ch) : (Ch-10 + L'A');
  1878. Ch = (BYTE)(Dword & 0x0F);
  1879. Dword >>= 4;
  1880. Stream[i*2 -2] = (Ch < 10)? (L'0'+Ch) : (Ch-10 + L'A');
  1881. }
  1882. *Str = L'\0';
  1883. return Str;
  1884. }
  1885. LPWSTR
  1886. ConvertBinaryToString( // convert a binary byte sequence to a string as 0F321B etc..
  1887. IN LPBYTE Bytes,
  1888. IN DWORD nBytes,
  1889. IN WCHAR PrefixChar,
  1890. IN LPWSTR Str
  1891. )
  1892. {
  1893. BYTE Ch, Ch1, Ch2;
  1894. DWORD i;
  1895. *Str ++ = PrefixChar;
  1896. for( i = 0; i < nBytes; i ++ ) {
  1897. Ch = *Bytes ++;
  1898. Ch1 = Ch >> 4;
  1899. Ch2 = Ch & 0x0F;
  1900. if( Ch1 >= 10 ) *Str ++ = Ch1 - 10 + L'A';
  1901. else *Str ++ = Ch1 + L'0';
  1902. if( Ch2 >= 10 ) *Str ++ = Ch2 - 10 + L'A';
  1903. else *Str ++ = Ch2 + L'0';
  1904. }
  1905. *Str = L'\0';
  1906. return Str;
  1907. }
  1908. DWORD
  1909. ConvertEAttribToString( // inverse of ConvertStringtoEAttrib
  1910. IN PEATTRIB Attrib, // the attrib to encapsulate
  1911. IN OUT LPWSTR *String, // allocated string
  1912. IN WCHAR Sep
  1913. )
  1914. {
  1915. DWORD nChars;
  1916. LPWSTR Str;
  1917. WCHAR PrefixChar;
  1918. AssertRet(String && Attrib, ERROR_INVALID_PARAMETER);
  1919. *String = NULL;
  1920. nChars = 0;
  1921. if( IS_ADDRESS1_PRESENT(Attrib) ) nChars += sizeof(L"$i000.000.000.000");
  1922. if( IS_ADDRESS2_PRESENT(Attrib) ) nChars += sizeof(L"$j000.000.000.000");
  1923. if( IS_ADDRESS3_PRESENT(Attrib) ) nChars += sizeof(L"$k000.000.000.000");
  1924. if( IS_ADSPATH_PRESENT(Attrib) ) {
  1925. AssertRet( IS_STOREGETTYPE_PRESENT(Attrib), ERROR_INVALID_PARAMETER );
  1926. AssertRet( Attrib->ADsPath, ERROR_INVALID_PARAMETER );
  1927. nChars += sizeof(WCHAR) * SizeAfterSeparation(Attrib->ADsPath,Sep);
  1928. nChars += sizeof(L"$p");
  1929. }
  1930. if( IS_FLAGS1_PRESENT(Attrib) ) nChars += sizeof(L"$f0x") + sizeof(DWORD)*2*sizeof(WCHAR);
  1931. if( IS_FLAGS2_PRESENT(Attrib) ) nChars += sizeof(L"$g0x") + sizeof(DWORD)*2*sizeof(WCHAR);
  1932. if( IS_DWORD1_PRESENT(Attrib) ) nChars += sizeof(L"$d0x") + sizeof(DWORD)*2*sizeof(WCHAR);
  1933. if( IS_DWORD2_PRESENT(Attrib) ) nChars += sizeof(L"$e0x") + sizeof(DWORD)*2*sizeof(WCHAR);
  1934. if( IS_STRING1_PRESENT(Attrib) ) {
  1935. AssertRet( Attrib->String1, ERROR_INVALID_PARAMETER );
  1936. nChars += sizeof(WCHAR) * SizeAfterSeparation(Attrib->String1,Sep);
  1937. nChars += sizeof(L"$s");
  1938. }
  1939. if( IS_STRING2_PRESENT(Attrib) ) {
  1940. AssertRet( Attrib->String2, ERROR_INVALID_PARAMETER );
  1941. nChars += sizeof(WCHAR) * SizeAfterSeparation(Attrib->String2,Sep);
  1942. nChars += sizeof(L"$t");
  1943. }
  1944. if( IS_STRING3_PRESENT(Attrib) ) {
  1945. AssertRet( Attrib->String3, ERROR_INVALID_PARAMETER );
  1946. nChars += sizeof(WCHAR) * SizeAfterSeparation(Attrib->String3,Sep);
  1947. nChars += sizeof(L"$u");
  1948. }
  1949. if( IS_STRING4_PRESENT(Attrib) ) {
  1950. AssertRet( Attrib->String4, ERROR_INVALID_PARAMETER );
  1951. nChars += sizeof(WCHAR) * SizeAfterSeparation(Attrib->String4,Sep);
  1952. nChars += sizeof(L"$v");
  1953. }
  1954. if( IS_BINARY1_PRESENT(Attrib) ) {
  1955. nChars += sizeof(WCHAR) * 2 * Attrib->BinLen1;
  1956. nChars += sizeof(L"$b");
  1957. }
  1958. if( IS_BINARY2_PRESENT(Attrib) ) {
  1959. nChars += sizeof(WCHAR) * 2 * Attrib->BinLen2;
  1960. nChars += sizeof(L"$c");
  1961. }
  1962. if( 0 == nChars ) return ERROR_SUCCESS; // nothing is present really.
  1963. Str = MemAlloc(nChars + sizeof(L"") ); // take care of terminating the string
  1964. if( NULL == Str ) return ERROR_NOT_ENOUGH_MEMORY;
  1965. *String = Str; // save the return value, as Str keeps changing
  1966. if( IS_ADDRESS1_PRESENT(Attrib) ) {
  1967. Str = ConvertAddressToString(Attrib->Address1, ch_Address1, Str);
  1968. *Str++ = Sep;
  1969. }
  1970. if( IS_ADDRESS2_PRESENT(Attrib) ) {
  1971. Str = ConvertAddressToString(Attrib->Address2, ch_Address2, Str);
  1972. *Str++ = Sep;
  1973. }
  1974. if( IS_ADDRESS3_PRESENT(Attrib) ) {
  1975. Str = ConvertAddressToString(Attrib->Address3, ch_Address3, Str);
  1976. *Str++ = Sep;
  1977. }
  1978. if( IS_ADSPATH_PRESENT(Attrib) ) {
  1979. switch(Attrib->StoreGetType) {
  1980. case StoreGetChildType:
  1981. PrefixChar = ch_ADsPath_relative; break;
  1982. case StoreGetAbsoluteSameServerType:
  1983. PrefixChar = ch_ADsPath_absolute; break;
  1984. case StoreGetAbsoluteOtherServerType:
  1985. PrefixChar = ch_ADsPath_diff_srvr; break;
  1986. default:
  1987. Require(FALSE); // too late to do anything about this now.
  1988. PrefixChar = ch_ADsPath_diff_srvr; break;
  1989. }
  1990. Str = ConvertStringToString(Attrib->ADsPath, PrefixChar, Str,Sep);
  1991. *Str++ = Sep;
  1992. }
  1993. if( IS_FLAGS1_PRESENT(Attrib) ) {
  1994. Str = ConvertDwordToString(Attrib->Flags1, ch_Flags1, Str);
  1995. *Str++ = Sep;
  1996. }
  1997. if( IS_FLAGS2_PRESENT(Attrib) ) {
  1998. Str = ConvertDwordToString(Attrib->Flags2, ch_Flags2, Str);
  1999. *Str++ = Sep;
  2000. }
  2001. if( IS_DWORD1_PRESENT(Attrib) ) {
  2002. Str = ConvertDwordToString(Attrib->Dword1, ch_Dword1, Str);
  2003. *Str++ = Sep;
  2004. }
  2005. if( IS_DWORD2_PRESENT(Attrib) ) {
  2006. Str = ConvertDwordToString(Attrib->Dword2, ch_Dword2, Str);
  2007. *Str++ = Sep;
  2008. }
  2009. if( IS_STRING1_PRESENT(Attrib) ) {
  2010. Str = ConvertStringToString(Attrib->String1, ch_String1, Str,Sep);
  2011. *Str++ = Sep;
  2012. }
  2013. if( IS_STRING2_PRESENT(Attrib) ) {
  2014. Str = ConvertStringToString(Attrib->String2, ch_String2, Str,Sep);
  2015. *Str++ = Sep;
  2016. }
  2017. if( IS_STRING3_PRESENT(Attrib) ) {
  2018. Str = ConvertStringToString(Attrib->String3, ch_String3, Str,Sep);
  2019. *Str++ = Sep;
  2020. }
  2021. if( IS_STRING4_PRESENT(Attrib) ) {
  2022. Str = ConvertStringToString(Attrib->String4, ch_String4, Str,Sep);
  2023. *Str++ = Sep;
  2024. }
  2025. if( IS_BINARY1_PRESENT(Attrib) ) {
  2026. Str = ConvertBinaryToString(Attrib->Binary1, Attrib->BinLen1, ch_Binary1, Str);
  2027. *Str++ = Sep;
  2028. }
  2029. if( IS_BINARY2_PRESENT(Attrib) ) {
  2030. Str = ConvertBinaryToString(Attrib->Binary2, Attrib->BinLen2, ch_Binary2, Str);
  2031. }
  2032. *Str = L'\0';
  2033. Require(((LPBYTE)Str) < nChars + 1 + ((LPBYTE)(*String)) );
  2034. return ERROR_SUCCESS;
  2035. }
  2036. LPBYTE
  2037. ConvertDwordToBinary( // pack a DWORD in binary format
  2038. IN DWORD Dword,
  2039. IN WCHAR Character,
  2040. IN LPBYTE Buffer
  2041. )
  2042. {
  2043. *(LPWORD)Buffer = htons(Character); Buffer += sizeof(WORD);
  2044. *(LPWORD)Buffer = htons(sizeof(DWORD)); Buffer += sizeof(WORD);
  2045. *(DWORD UNALIGNED *)Buffer = htonl(Dword);
  2046. Buffer += sizeof(DWORD);
  2047. return Buffer;
  2048. }
  2049. LPBYTE
  2050. ConvertAddressToBinary( // pack an address to binary format..
  2051. IN DWORD Address,
  2052. IN WCHAR Character,
  2053. IN LPBYTE Buffer
  2054. )
  2055. {
  2056. return ConvertDwordToBinary(Address,Character,Buffer);
  2057. }
  2058. LPBYTE
  2059. ConvertStringToBinary( // pack a string in binary format
  2060. IN LPWSTR Str,
  2061. IN WCHAR Character,
  2062. IN LPBYTE Buffer
  2063. )
  2064. {
  2065. DWORD Size;
  2066. Size = sizeof(WCHAR)*(1+wcslen(Str));
  2067. *(LPWORD)Buffer = htons(Character); Buffer += sizeof(WORD);
  2068. *(LPWORD)Buffer = htons((WORD)Size); Buffer += sizeof(WORD);
  2069. memcpy(Buffer, Str, Size);
  2070. Buffer += ROUND_UP_COUNT(Size, ALIGN_WORD);
  2071. return Buffer;
  2072. }
  2073. DWORD
  2074. ConvertEAttribToBinary( // inverse of ConvertBinarytoEAttrib
  2075. IN PEATTRIB Attrib, // the attrib to encapsulate
  2076. IN OUT LPBYTE *Bytes, // allocated buffer
  2077. IN OUT DWORD *nBytes // # of bytes allocated
  2078. )
  2079. {
  2080. DWORD nChars;
  2081. LPBYTE Buf;
  2082. WCHAR PrefixChar;
  2083. AssertRet(Bytes && Attrib && nBytes, ERROR_INVALID_PARAMETER);
  2084. *Bytes = NULL; *nBytes =0;
  2085. nChars = 0; // WCHAR_opcode ~ WORD_size ~ DWORD_ipAddress
  2086. if( IS_ADDRESS1_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD);
  2087. if( IS_ADDRESS2_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD);
  2088. if( IS_ADDRESS3_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD);
  2089. if( IS_ADSPATH_PRESENT(Attrib) ) {
  2090. AssertRet( IS_STOREGETTYPE_PRESENT(Attrib), ERROR_INVALID_PARAMETER );
  2091. AssertRet( Attrib->ADsPath, ERROR_INVALID_PARAMETER );
  2092. nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
  2093. nChars += sizeof(WCHAR) * (1+ wcslen(Attrib->ADsPath));
  2094. }
  2095. // WCHAR_opcode ~ WORD_size ~ DWORD_flags
  2096. if( IS_FLAGS1_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD);
  2097. if( IS_FLAGS2_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD);
  2098. if( IS_DWORD1_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD);
  2099. if( IS_DWORD2_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD);
  2100. if( IS_STRING1_PRESENT(Attrib) ) {
  2101. AssertRet( Attrib->String1, ERROR_INVALID_PARAMETER );
  2102. nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
  2103. nChars += sizeof(WCHAR) * (1 + wcslen(Attrib->String1));
  2104. }
  2105. if( IS_STRING2_PRESENT(Attrib) ) {
  2106. AssertRet( Attrib->String2, ERROR_INVALID_PARAMETER );
  2107. nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
  2108. nChars += sizeof(WCHAR) * (1 + wcslen(Attrib->String2));
  2109. }
  2110. if( IS_STRING3_PRESENT(Attrib) ) {
  2111. AssertRet( Attrib->String3, ERROR_INVALID_PARAMETER );
  2112. nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
  2113. nChars += sizeof(WCHAR) * (1 + wcslen(Attrib->String3));
  2114. }
  2115. if( IS_STRING4_PRESENT(Attrib) ) {
  2116. AssertRet( Attrib->String4, ERROR_INVALID_PARAMETER );
  2117. nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
  2118. nChars += sizeof(WCHAR) * (1 + wcslen(Attrib->String4));
  2119. }
  2120. if( IS_BINARY1_PRESENT(Attrib) ) {
  2121. nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
  2122. nChars += ROUND_UP_COUNT(Attrib->BinLen1, ALIGN_WORD);
  2123. }
  2124. if( IS_BINARY2_PRESENT(Attrib) ) {
  2125. nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
  2126. nChars += ROUND_UP_COUNT(Attrib->BinLen2, ALIGN_WORD);
  2127. }
  2128. if( 0 == nChars ) return ERROR_SUCCESS; // nothing is present really.
  2129. Buf = MemAlloc(nChars);
  2130. if( NULL == Buf ) return ERROR_NOT_ENOUGH_MEMORY;
  2131. *Bytes = Buf; // save the return value.. Buf itself is changed..
  2132. *nBytes = nChars;
  2133. if( IS_ADDRESS1_PRESENT(Attrib) ) Buf = ConvertAddressToBinary(Attrib->Address1, ch_Address1, Buf);
  2134. if( IS_ADDRESS2_PRESENT(Attrib) ) Buf = ConvertAddressToBinary(Attrib->Address2, ch_Address2, Buf);
  2135. if( IS_ADDRESS3_PRESENT(Attrib) ) Buf = ConvertAddressToBinary(Attrib->Address3, ch_Address3, Buf);
  2136. if( IS_ADSPATH_PRESENT(Attrib) ) {
  2137. switch(Attrib->StoreGetType) {
  2138. case StoreGetChildType:
  2139. PrefixChar = ch_ADsPath_relative; break;
  2140. case StoreGetAbsoluteSameServerType:
  2141. PrefixChar = ch_ADsPath_absolute; break;
  2142. case StoreGetAbsoluteOtherServerType:
  2143. PrefixChar = ch_ADsPath_diff_srvr; break;
  2144. default:
  2145. Require(FALSE); // too late to do anything about this now.
  2146. PrefixChar = ch_ADsPath_diff_srvr; break;
  2147. }
  2148. Buf = ConvertStringToBinary(Attrib->ADsPath, PrefixChar, Buf);
  2149. }
  2150. if( IS_FLAGS1_PRESENT(Attrib) ) Buf = ConvertDwordToBinary(Attrib->Flags1, ch_Flags1, Buf);
  2151. if( IS_FLAGS2_PRESENT(Attrib) ) Buf = ConvertDwordToBinary(Attrib->Flags2, ch_Flags2, Buf);
  2152. if( IS_DWORD1_PRESENT(Attrib) ) Buf = ConvertDwordToBinary(Attrib->Dword1, ch_Dword1, Buf);
  2153. if( IS_DWORD2_PRESENT(Attrib) ) Buf = ConvertDwordToBinary(Attrib->Dword2, ch_Dword2, Buf);
  2154. if( IS_STRING1_PRESENT(Attrib) ) Buf = ConvertStringToBinary(Attrib->String1, ch_String1, Buf);
  2155. if( IS_STRING2_PRESENT(Attrib) ) Buf = ConvertStringToBinary(Attrib->String2, ch_String2, Buf);
  2156. if( IS_STRING3_PRESENT(Attrib) ) Buf = ConvertStringToBinary(Attrib->String3, ch_String3, Buf);
  2157. if( IS_STRING4_PRESENT(Attrib) ) Buf = ConvertStringToBinary(Attrib->String4, ch_String4, Buf);
  2158. if( IS_BINARY1_PRESENT(Attrib) ) {
  2159. *(LPWORD)Buf = htons(ch_Binary1); Buf += sizeof(WORD);
  2160. *(LPWORD)Buf = htons((WORD)Attrib->BinLen1); Buf += sizeof(WORD);
  2161. memcpy(Buf, Attrib->Binary1, Attrib->BinLen1);
  2162. Buf += ROUND_UP_COUNT(Attrib->BinLen1, ALIGN_WORD);
  2163. }
  2164. if( IS_BINARY2_PRESENT(Attrib) ) {
  2165. *(LPWORD)Buf = htons(ch_Binary2); Buf += sizeof(WORD);
  2166. *(LPWORD)Buf = htons((WORD)Attrib->BinLen2); Buf += sizeof(WORD);
  2167. memcpy(Buf, Attrib->Binary2, Attrib->BinLen2);
  2168. Buf += ROUND_UP_COUNT(Attrib->BinLen2, ALIGN_WORD);
  2169. }
  2170. Require( Buf == nChars + (*Bytes) );
  2171. return ERROR_SUCCESS;
  2172. }
  2173. StoreUpdateAttributesInternal( // update a list of attributes
  2174. IN OUT LPSTORE_HANDLE hStore, // handle to obj to update
  2175. IN DWORD Reserved, // for future use, must be zero
  2176. IN LPWSTR AttribName, // name of attrib, must be string type
  2177. IN PARRAY Array, // list of attribs
  2178. IN WCHAR Sep
  2179. ) //EndExport(function)
  2180. {
  2181. DWORD Result;
  2182. HRESULT hResult;
  2183. LONG nValues, i;
  2184. ADS_ATTR_INFO Attribute;
  2185. PADSVALUE Values;
  2186. ARRAY_LOCATION Loc;
  2187. LPWSTR Str;
  2188. PEATTRIB ThisAttrib;
  2189. if( NULL == hStore || NULL == hStore->ADSIHandle )
  2190. return ERROR_INVALID_PARAMETER;
  2191. if( NULL == AttribName || 0 != Reserved )
  2192. return ERROR_INVALID_PARAMETER;
  2193. if( NULL == Array )
  2194. return ERROR_INVALID_PARAMETER;
  2195. nValues = MemArraySize(Array);
  2196. if( 0 == nValues ) { // delete the attribute
  2197. Attribute.pszAttrName = AttribName;
  2198. Attribute.dwControlCode = ADS_ATTR_CLEAR;
  2199. Attribute.dwADsType = ADSTYPE_CASE_IGNORE_STRING;
  2200. Attribute.pADsValues = NULL;
  2201. Attribute.dwNumValues = 0;
  2202. hResult = ADSISetObjectAttributes(
  2203. /* hDSObject */ hStore->ADSIHandle,
  2204. /* pAttributeEntr.. */ &Attribute,
  2205. /* dwNumAttributes */ 1,
  2206. /* pdwNumAttribut.. */ &nValues
  2207. );
  2208. if( FAILED(hResult) || 1 != nValues ) { // something went wrong
  2209. return ConvertHresult(hResult);
  2210. }
  2211. return ERROR_SUCCESS;
  2212. }
  2213. Values = MemAlloc(nValues * sizeof(ADSVALUE));
  2214. if( NULL == Values ) { // could not allocate ADs array
  2215. return ERROR_NOT_ENOUGH_MEMORY;
  2216. }
  2217. for(i = 0, Result = MemArrayInitLoc(Array, &Loc)
  2218. ; ERROR_FILE_NOT_FOUND != Result ; // convert to PADS_ATTR_INFO
  2219. i ++ , Result = MemArrayNextLoc(Array, &Loc)
  2220. ) {
  2221. Result = MemArrayGetElement(Array, &Loc, &ThisAttrib);
  2222. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  2223. Str = NULL;
  2224. Result = ConvertEAttribToString(ThisAttrib, &Str, Sep);
  2225. if( ERROR_SUCCESS != Result ) { // something went wrong!
  2226. goto Cleanup; // free allocated memory
  2227. }
  2228. Values[i].dwType = ADSTYPE_CASE_IGNORE_STRING;
  2229. Values[i].CaseIgnoreString = Str;
  2230. }
  2231. Attribute.pszAttrName = AttribName;
  2232. Attribute.dwControlCode = ADS_ATTR_UPDATE;
  2233. Attribute.dwADsType = ADSTYPE_CASE_IGNORE_STRING;
  2234. Attribute.pADsValues = Values;
  2235. Attribute.dwNumValues = nValues;
  2236. hResult = ADSISetObjectAttributes(
  2237. /* hDSObject */ hStore->ADSIHandle,
  2238. /* pAttributeEntr.. */ &Attribute,
  2239. /* dwNumAttributes */ 1,
  2240. /* pdwNumAttribut.. */ &nValues
  2241. );
  2242. if( FAILED(hResult) || 1 != nValues ) { // something went wrong
  2243. Result = ConvertHresult(hResult);
  2244. } else Result = ERROR_SUCCESS;
  2245. Cleanup:
  2246. if( Values ) { // got to free allocated memory
  2247. while( i -- ) { // got to free converted strings
  2248. if( Values[i].CaseIgnoreString )
  2249. MemFree(Values[i].CaseIgnoreString);
  2250. }
  2251. MemFree(Values);
  2252. }
  2253. return Result;
  2254. }
  2255. //BeginExport(function)
  2256. //DOC StoreUpdateAttributes is sort of the converse of StoreCollectAttributes.
  2257. //DOC This function takes an array of type EATTRIB elements and updates the DS
  2258. //DOC with this array. This function does not work when the attrib is of type
  2259. //DOC OCTET_STRING etc. It works only with types that can be derived from
  2260. //DOC PrintableString.
  2261. DWORD
  2262. StoreUpdateAttributes( // update a list of attributes
  2263. IN OUT LPSTORE_HANDLE hStore, // handle to obj to update
  2264. IN DWORD Reserved, // for future use, must be zero
  2265. IN LPWSTR AttribName, // name of attrib, must be string type
  2266. IN PARRAY Array // list of attribs
  2267. ) //EndExport(function)
  2268. {
  2269. DWORD Result;
  2270. HRESULT hResult;
  2271. Result = StoreUpdateAttributesInternal(
  2272. hStore, Reserved, AttribName, Array, ch_FieldSep );
  2273. return Result;
  2274. }
  2275. //BeginExport(function)
  2276. //DOC StoreUpdateBinaryAttributes is sort of the converse of StoreCollectBinaryAttributes
  2277. //DOC This function takes an array of type EATTRIB elements and updates the DS
  2278. //DOC with this array. This function works only when the attrib is of type
  2279. //DOC OCTET_STRING etc. It doesnt work with types that can be derived from
  2280. //DOC PrintableString!!!.
  2281. DWORD
  2282. StoreUpdateBinaryAttributes( // update a list of attributes
  2283. IN OUT LPSTORE_HANDLE hStore, // handle to obj to update
  2284. IN DWORD Reserved, // for future use, must be zero
  2285. IN LPWSTR AttribName, // name of attrib, must be OCTET_STRING type
  2286. IN PARRAY Array // list of attribs
  2287. ) //EndExport(function)
  2288. {
  2289. DWORD Result;
  2290. HRESULT hResult;
  2291. LONG nValues, i, nBytes;
  2292. ADS_ATTR_INFO Attribute;
  2293. PADSVALUE Values;
  2294. ARRAY_LOCATION Loc;
  2295. LPBYTE Bytes;
  2296. PEATTRIB ThisAttrib;
  2297. if( NULL == hStore || NULL == hStore->ADSIHandle )
  2298. return ERROR_INVALID_PARAMETER;
  2299. if( NULL == AttribName || 0 != Reserved )
  2300. return ERROR_INVALID_PARAMETER;
  2301. if( NULL == Array )
  2302. return ERROR_INVALID_PARAMETER;
  2303. nValues = MemArraySize(Array);
  2304. if( 0 == nValues ) { // delete the attribute
  2305. Attribute.pszAttrName = AttribName;
  2306. Attribute.dwControlCode = ADS_ATTR_CLEAR;
  2307. Attribute.dwADsType = ADSTYPE_OCTET_STRING;
  2308. Attribute.pADsValues = NULL;
  2309. Attribute.dwNumValues = 0;
  2310. hResult = ADSISetObjectAttributes(
  2311. /* hDSObject */ hStore->ADSIHandle,
  2312. /* pAttributeEntr.. */ &Attribute,
  2313. /* dwNumAttributes */ 1,
  2314. /* pdwNumAttribut.. */ &nValues
  2315. );
  2316. if( FAILED(hResult) || 1 != nValues ) { // something went wrong
  2317. return ConvertHresult(hResult);
  2318. }
  2319. return ERROR_SUCCESS;
  2320. }
  2321. Values = MemAlloc(nValues * sizeof(ADSVALUE));
  2322. if( NULL == Values ) { // could not allocate ADs array
  2323. return ERROR_NOT_ENOUGH_MEMORY;
  2324. }
  2325. for(i = 0, Result = MemArrayInitLoc(Array, &Loc)
  2326. ; ERROR_FILE_NOT_FOUND != Result ; // convert to PADS_ATTR_INFO
  2327. i ++ , Result = MemArrayNextLoc(Array, &Loc)
  2328. ) {
  2329. Result = MemArrayGetElement(Array, &Loc, &ThisAttrib);
  2330. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  2331. Bytes = NULL; nBytes =0;
  2332. Result = ConvertEAttribToBinary(ThisAttrib, &Bytes, &nBytes);
  2333. if( ERROR_SUCCESS != Result ) { // something went wrong!
  2334. goto Cleanup; // free allocated memory
  2335. }
  2336. Values[i].dwType = ADSTYPE_OCTET_STRING;
  2337. Values[i].OctetString.dwLength = nBytes;
  2338. Values[i].OctetString.lpValue = Bytes;
  2339. }
  2340. Attribute.pszAttrName = AttribName;
  2341. Attribute.dwControlCode = ADS_ATTR_UPDATE;
  2342. Attribute.dwADsType = ADSTYPE_OCTET_STRING;
  2343. Attribute.pADsValues = Values;
  2344. Attribute.dwNumValues = nValues;
  2345. hResult = ADSISetObjectAttributes(
  2346. /* hDSObject */ hStore->ADSIHandle,
  2347. /* pAttributeEntr.. */ &Attribute,
  2348. /* dwNumAttributes */ 1,
  2349. /* pdwNumAttribut.. */ &nValues
  2350. );
  2351. if( FAILED(hResult) || 1 != nValues ) { // something went wrong
  2352. Result = ConvertHresult(hResult);
  2353. } else Result = ERROR_SUCCESS;
  2354. Cleanup:
  2355. if( Values ) { // got to free allocated memory
  2356. while( i -- ) { // got to free converted strings
  2357. if( Values[i].OctetString.lpValue )
  2358. MemFree(Values[i].OctetString.lpValue);
  2359. }
  2360. MemFree(Values);
  2361. }
  2362. return Result;
  2363. }
  2364. //================================================================================
  2365. // end of file
  2366. //================================================================================