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.

1282 lines
34 KiB

  1. #include "nds.hxx"
  2. #pragma hdrstop
  3. FILTERS Filters[] = {
  4. {L"user", NDS_USER_ID},
  5. {L"group", NDS_GROUP_ID},
  6. {L"queue", NDS_PRINTER_ID},
  7. {L"domain", NDS_DOMAIN_ID},
  8. {L"computer", NDS_COMPUTER_ID},
  9. {L"service", NDS_SERVICE_ID},
  10. {L"fileservice", NDS_FILESERVICE_ID},
  11. {L"fileshare", NDS_FILESHARE_ID},
  12. {L"class", NDS_CLASS_ID},
  13. {L"functionalset", NDS_FUNCTIONALSET_ID},
  14. {L"syntax", NDS_SYNTAX_ID},
  15. {L"property", NDS_PROPERTY_ID},
  16. {L"tree", NDS_TREE_ID},
  17. {L"Organizational Unit", NDS_OU_ID},
  18. {L"Organization", NDS_O_ID},
  19. {L"Locality", NDS_LOCALITY_ID}
  20. };
  21. #define MAX_FILTERS (sizeof(Filters)/sizeof(FILTERS))
  22. PFILTERS gpFilters = Filters;
  23. DWORD gdwMaxFilters = MAX_FILTERS;
  24. extern WCHAR * szProviderName;
  25. struct _err_lookup_ {
  26. LPWSTR errString;
  27. int errNo;
  28. } g_aErrLookup[] = {
  29. {L"ERR_INSUFFICIENT_MEMORY ", -150 },
  30. {L"ERR_REQUEST_UNKNOWN ", -251 },
  31. {L"ERR_OF_SOME_SORT ", -255 },
  32. {L"ERR_NOT_ENOUGH_MEMORY ", -301 },
  33. {L"ERR_BAD_KEY ", -302 },
  34. {L"ERR_BAD_CONTEXT ", -303 },
  35. {L"ERR_BUFFER_FULL ", -304 },
  36. {L"ERR_LIST_EMPTY ", -305 },
  37. {L"ERR_BAD_SYNTAX ", -306 },
  38. {L"ERR_BUFFER_EMPTY ", -307 },
  39. {L"ERR_BAD_VERB ", -308 },
  40. {L"ERR_EXPECTED_IDENTIFIER ", -309 },
  41. {L"ERR_EXPECTED_EQUALS ", -310 },
  42. {L"ERR_ATTR_TYPE_EXPECTED ", -311 },
  43. {L"ERR_ATTR_TYPE_NOT_EXPECTED ", -312 },
  44. {L"ERR_FILTER_TREE_EMPTY ", -313 },
  45. {L"ERR_INVALID_OBJECT_NAME ", -314 },
  46. {L"ERR_EXPECTED_RDN_DELIMITER ", -315 },
  47. {L"ERR_TOO_MANY_TOKENS ", -316 },
  48. {L"ERR_INCONSISTENT_MULTIAVA ", -317 },
  49. {L"ERR_COUNTRY_NAME_TOO_LONG ", -318 },
  50. {L"ERR_SYSTEM_ERROR ", -319 },
  51. {L"ERR_CANT_ADD_ROOT ", -320 },
  52. {L"ERR_UNABLE_TO_ATTACH ", -321 },
  53. {L"ERR_INVALID_HANDLE ", -322 },
  54. {L"ERR_BUFFER_ZERO_LENGTH ", -323 },
  55. {L"ERR_INVALID_REPLICA_TYPE ", -324 },
  56. {L"ERR_INVALID_ATTR_SYNTAX ", -325 },
  57. {L"ERR_INVALID_FILTER_SYNTAX ", -326 },
  58. {L"ERR_CONTEXT_CREATION ", -328 },
  59. {L"ERR_INVALID_UNION_TAG ", -329 },
  60. {L"ERR_INVALID_SERVER_RESPONSE ", -330 },
  61. {L"ERR_NULL_POINTER ", -331 },
  62. {L"ERR_NO_SERVER_FOUND ", -332 },
  63. {L"ERR_NO_CONNECTION ", -333 },
  64. {L"ERR_RDN_TOO_LONG ", -334 },
  65. {L"ERR_DUPLICATE_TYPE ", -335 },
  66. {L"ERR_DATA_STORE_FAILURE ", -336 },
  67. {L"ERR_NOT_LOGGED_IN ", -337 },
  68. {L"ERR_INVALID_PASSWORD_CHARS ", -338 },
  69. {L"ERR_FAILED_SERVER_AUTHENT ", -339 },
  70. {L"ERR_TRANSPORT ", -340 },
  71. {L"ERR_NO_SUCH_SYNTAX ", -341 },
  72. {L"ERR_INVALID_DS_NAME ", -342 },
  73. {L"ERR_ATTR_NAME_TOO_LONG ", -343 },
  74. {L"ERR_INVALID_TDS ", -344 },
  75. {L"ERR_INVALID_DS_VERSION ", -345 },
  76. {L"ERR_UNICODE_TRANSLATION ", -346 },
  77. {L"ERR_SCHEMA_NAME_TOO_LONG ", -347 },
  78. {L"ERR_UNICODE_FILE_NOT_FOUND ", -348 },
  79. {L"ERR_UNICODE_ALREADY_LOADED ", -349 },
  80. {L"ERR_NOT_CONTEXT_OWNER ", -350 },
  81. {L"ERR_ATTEMPT_TO_AUTHENTICATE_0 ", -351 },
  82. {L"ERR_NO_WRITABLE_REPLICAS ", -352 },
  83. {L"ERR_DN_TOO_LONG ", -353 },
  84. {L"ERR_RENAME_NOT_ALLOWED ", -354 },
  85. {L"ERR_NO_SUCH_ENTRY ", -601 },
  86. {L"ERR_NO_SUCH_VALUE ", -602 },
  87. {L"ERR_NO_SUCH_ATTRIBUTE ", -603 },
  88. {L"ERR_NO_SUCH_CLASS ", -604 },
  89. {L"ERR_NO_SUCH_PARTITION ", -605 },
  90. {L"ERR_ENTRY_ALREADY_EXISTS ", -606 },
  91. {L"ERR_NOT_EFFECTIVE_CLASS ", -607 },
  92. {L"ERR_ILLEGAL_ATTRIBUTE ", -608 },
  93. {L"ERR_MISSING_MANDATORY ", -609 },
  94. {L"ERR_ILLEGAL_DS_NAME ", -610 },
  95. {L"ERR_ILLEGAL_CONTAINMENT ", -611 },
  96. {L"ERR_CANT_HAVE_MULTIPLE_VALUES ", -612 },
  97. {L"ERR_SYNTAX_VIOLATION ", -613 },
  98. {L"ERR_DUPLICATE_VALUE ", -614 },
  99. {L"ERR_ATTRIBUTE_ALREADY_EXISTS ", -615 },
  100. {L"ERR_MAXIMUM_ENTRIES_EXIST ", -616 },
  101. {L"ERR_DATABASE_FORMAT ", -617 },
  102. {L"ERR_INCONSISTENT_DATABASE ", -618 },
  103. {L"ERR_INVALID_COMPARISON ", -619 },
  104. {L"ERR_COMPARISON_FAILED ", -620 },
  105. {L"ERR_TRANSACTIONS_DISABLED ", -621 },
  106. {L"ERR_INVALID_TRANSPORT ", -622 },
  107. {L"ERR_SYNTAX_INVALID_IN_NAME ", -623 },
  108. {L"ERR_REPLICA_ALREADY_EXISTS ", -624 },
  109. {L"ERR_TRANSPORT_FAILURE ", -625 },
  110. {L"ERR_ALL_REFERRALS_FAILED ", -626 },
  111. {L"ERR_CANT_REMOVE_NAMING_VALUE ", -627 },
  112. {L"ERR_OBJECT_CLASS_VIOLATION ", -628 },
  113. {L"ERR_ENTRY_IS_NOT_LEAF ", -629 },
  114. {L"ERR_DIFFERENT_TREE ", -630 },
  115. {L"ERR_ILLEGAL_REPLICA_TYPE ", -631 },
  116. {L"ERR_SYSTEM_FAILURE ", -632 },
  117. {L"ERR_INVALID_ENTRY_FOR_ROOT ", -633 },
  118. {L"ERR_NO_REFERRALS ", -634 },
  119. {L"ERR_REMOTE_FAILURE ", -635 },
  120. {L"ERR_UNREACHABLE_SERVER ", -636 },
  121. {L"ERR_PREVIOUS_MOVE_IN_PROGRESS ", -637 },
  122. {L"ERR_NO_CHARACTER_MAPPING ", -638 },
  123. {L"ERR_INCOMPLETE_AUTHENTICATION ", -639 },
  124. {L"ERR_INVALID_CERTIFICATE ", -640 },
  125. {L"ERR_INVALID_REQUEST ", -641 },
  126. {L"ERR_INVALID_ITERATION ", -642 },
  127. {L"ERR_SCHEMA_IS_NONREMOVABLE ", -643 },
  128. {L"ERR_SCHEMA_IS_IN_USE ", -644 },
  129. {L"ERR_CLASS_ALREADY_EXISTS ", -645 },
  130. {L"ERR_BAD_NAMING_ATTRIBUTES ", -646 },
  131. {L"ERR_NOT_ROOT_PARTITION ", -647 },
  132. {L"ERR_INSUFFICIENT_STACK ", -648 },
  133. {L"ERR_INSUFFICIENT_BUFFER ", -649 },
  134. {L"ERR_AMBIGUOUS_CONTAINMENT ", -650 },
  135. {L"ERR_AMBIGUOUS_NAMING ", -651 },
  136. {L"ERR_DUPLICATE_MANDATORY ", -652 },
  137. {L"ERR_DUPLICATE_OPTIONAL ", -653 },
  138. {L"ERR_PARTITION_BUSY ", -654 },
  139. {L"ERR_MULTIPLE_REPLICAS ", -655 },
  140. {L"ERR_CRUCIAL_REPLICA ", -656 },
  141. {L"ERR_SCHEMA_SYNC_IN_PROGRESS ", -657 },
  142. {L"ERR_SKULK_IN_PROGRESS ", -658 },
  143. {L"ERR_TIME_NOT_SYNCHRONIZED ", -659 },
  144. {L"ERR_RECORD_IN_USE ", -660 },
  145. {L"ERR_DS_VOLUME_NOT_MOUNTED ", -661 },
  146. {L"ERR_DS_VOLUME_IO_FAILURE ", -662 },
  147. {L"ERR_DS_LOCKED ", -663 },
  148. {L"ERR_OLD_EPOCH ", -664 },
  149. {L"ERR_NEW_EPOCH ", -665 },
  150. {L"ERR_INCOMPATIBLE_DS_VERSION ", -666 },
  151. {L"ERR_PARTITION_ROOT ", -667 },
  152. {L"ERR_ENTRY_NOT_CONTAINER ", -668 },
  153. {L"ERR_FAILED_AUTHENTICATION ", -669 },
  154. {L"ERR_INVALID_CONTEXT ", -670 },
  155. {L"ERR_NO_SUCH_PARENT ", -671 },
  156. {L"ERR_NO_ACCESS ", -672 },
  157. {L"ERR_REPLICA_NOT_ON ", -673 },
  158. {L"ERR_INVALID_NAME_SERVICE ", -674 },
  159. {L"ERR_INVALID_TASK ", -675 },
  160. {L"ERR_INVALID_CONN_HANDLE ", -676 },
  161. {L"ERR_INVALID_IDENTITY ", -677 },
  162. {L"ERR_DUPLICATE_ACL ", -678 },
  163. {L"ERR_PARTITION_ALREADY_EXISTS ", -679 },
  164. {L"ERR_TRANSPORT_MODIFIED ", -680 },
  165. {L"ERR_ALIAS_OF_AN_ALIAS ", -681 },
  166. {L"ERR_AUDITING_FAILED ", -682 },
  167. {L"ERR_INVALID_API_VERSION ", -683 },
  168. {L"ERR_SECURE_NCP_VIOLATION ", -684 },
  169. {L"ERR_MOVE_IN_PROGRESS ", -685 },
  170. {L"ERR_NOT_LEAF_PARTITION ", -686 },
  171. {L"ERR_CANNOT_ABORT ", -687 },
  172. {L"ERR_CACHE_OVERFLOW ", -688 },
  173. {L"ERR_INVALID_SUBORDINATE_COUNT ", -689 },
  174. {L"ERR_INVALID_RDN ", -690 },
  175. {L"ERR_MOD_TIME_NOT_CURRENT ", -691 },
  176. {L"ERR_INCORRECT_BASE_CLASS ", -692 },
  177. {L"ERR_MISSING_REFERENCE ", -693 },
  178. {L"ERR_LOST_ENTRY ", -694 },
  179. {L"ERR_AGENT_ALREADY_REGISTERED ", -695 },
  180. {L"ERR_DS_LOADER_BUSY ", -696 },
  181. {L"ERR_DS_CANNOT_RELOAD ", -697 },
  182. {L"ERR_REPLICA_IN_SKULK ", -698 },
  183. {L"ERR_FATAL ", -699 },
  184. {L"ERR_OBSOLETE_API ", -700 },
  185. {L"ERR_SYNCHRONIZATION_DISABLED ", -701 },
  186. {L"ERR_INVALID_PARAMETER ", -702 },
  187. {L"ERR_DUPLICATE_TEMPLATE ", -703 },
  188. {L"ERR_NO_MASTER_REPLICA ", -704 },
  189. {L"ERR_DUPLICATE_CONTAINMENT ", -705 },
  190. {L"ERR_NOT_SIBLING ", -706 },
  191. {L"ERR_INVALID_SIGNATURE ", -707 },
  192. {L"ERR_INVALID_RESPONSE ", -708 },
  193. {L"ERR_INSUFFICIENT_SOCKETS ", -709 },
  194. {L"ERR_DATABASE_READ_FAIL ", -710 },
  195. {L"ERR_INVALID_CODE_PAGE ", -711 },
  196. {L"ERR_INVALID_ESCAPE_CHAR ", -712 },
  197. {L"ERR_INVALID_DELIMITERS ", -713 },
  198. {L"ERR_NOT_IMPLEMENTED ", -714 },
  199. {L"ERR_CHECKSUM_FAILURE ", -715 },
  200. {L"ERR_CHECKSUMMING_NOT_SUPPORTED ", -716 },
  201. {L"ERR_CRC_FAILURE ", -717 }
  202. };
  203. DWORD g_cErrLookup = sizeof(g_aErrLookup)/sizeof(g_aErrLookup[0]);
  204. //+------------------------------------------------------------------------
  205. //
  206. // Class: Common
  207. //
  208. // Purpose: Contains Winnt routines and properties that are common to
  209. // all Winnt objects. Winnt objects get the routines and
  210. // properties through C++ inheritance.
  211. //
  212. //-------------------------------------------------------------------------
  213. HRESULT
  214. BuildADsPath(
  215. BSTR Parent,
  216. BSTR Name,
  217. BSTR *pADsPath
  218. )
  219. {
  220. LPWSTR lpADsPath = NULL;
  221. WCHAR ProviderName[MAX_PATH];
  222. HRESULT hr = S_OK;
  223. DWORD dwLen = 0;
  224. LPWSTR pszDisplayName = NULL;
  225. //
  226. // We will assert if bad parameters are passed to us.
  227. // This is because this should never be the case. This
  228. // is an internal call
  229. //
  230. ADsAssert(Parent && Name);
  231. ADsAssert(pADsPath);
  232. //
  233. // Get the display name for the name; The display name will have the proper
  234. // escaping for characters that have special meaning in an ADsPath like
  235. // '/' etc.
  236. //
  237. hr = GetDisplayName(
  238. Name,
  239. &pszDisplayName
  240. );
  241. BAIL_ON_FAILURE(hr);
  242. //
  243. // Special case the Namespace object; if
  244. // the parent is L"ADs:", then Name = ADsPath
  245. //
  246. if (!_wcsicmp(Parent, L"ADs:")) {
  247. hr = ADsAllocString( pszDisplayName, pADsPath);
  248. BAIL_ON_FAILURE(hr);
  249. goto cleanup;
  250. }
  251. //
  252. // Allocate the right side buffer
  253. // 2 for // + a buffer of MAX_PATH
  254. //
  255. dwLen = wcslen(Parent) + wcslen(pszDisplayName) + 2 + MAX_PATH;
  256. lpADsPath = (LPWSTR)AllocADsMem(dwLen*sizeof(WCHAR));
  257. if (!lpADsPath) {
  258. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  259. }
  260. //
  261. // The rest of the cases we expect valid data,
  262. // Path, Parent and Name are read-only, the end-user
  263. // cannot modify this data
  264. //
  265. //
  266. // For the first object, the domain object we do not add
  267. // the first backslash; so we examine that the parent is
  268. // L"WinNT:" and skip the slash otherwise we start with
  269. // the slash
  270. //
  271. wsprintf(ProviderName, L"%s:", szProviderName);
  272. wcscpy(lpADsPath, Parent);
  273. if (_wcsicmp(lpADsPath, ProviderName)) {
  274. wcscat(lpADsPath, L"/");
  275. }else {
  276. wcscat(lpADsPath, L"//");
  277. }
  278. wcscat(lpADsPath, pszDisplayName);
  279. hr = ADsAllocString( lpADsPath, pADsPath);
  280. cleanup:
  281. error:
  282. if (lpADsPath) {
  283. FreeADsMem(lpADsPath);
  284. }
  285. if (pszDisplayName) {
  286. FreeADsMem(pszDisplayName);
  287. }
  288. RRETURN(hr);
  289. }
  290. HRESULT
  291. BuildSchemaPath(
  292. BSTR bstrADsPath,
  293. BSTR bstrClass,
  294. BSTR *pSchemaPath
  295. )
  296. {
  297. WCHAR ADsSchema[MAX_PATH];
  298. OBJECTINFO ObjectInfo;
  299. POBJECTINFO pObjectInfo = &ObjectInfo;
  300. CLexer Lexer(bstrADsPath);
  301. HRESULT hr = S_OK;
  302. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  303. wcscpy(ADsSchema, L"");
  304. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  305. if (bstrClass && *bstrClass) {
  306. hr = ADsObject(&Lexer, pObjectInfo);
  307. BAIL_ON_FAILURE(hr);
  308. if (pObjectInfo->TreeName) {
  309. wsprintf(ADsSchema,L"%s://",pObjectInfo->ProviderName);
  310. wcscat(ADsSchema, pObjectInfo->TreeName);
  311. wcscat(ADsSchema,L"/schema/");
  312. wcscat(ADsSchema, bstrClass);
  313. }
  314. }
  315. hr = ADsAllocString( ADsSchema, pSchemaPath);
  316. error:
  317. if (pObjectInfo) {
  318. FreeObjectInfo( pObjectInfo );
  319. }
  320. RRETURN(hr);
  321. }
  322. HRESULT
  323. BuildADsGuid(
  324. REFCLSID clsid,
  325. BSTR *pADsClass
  326. )
  327. {
  328. WCHAR ADsClass[MAX_PATH];
  329. if (!StringFromGUID2(clsid, ADsClass, MAX_PATH)) {
  330. //
  331. // MAX_PATH should be more than enough for the GUID.
  332. //
  333. ADsAssert(!"GUID too big !!!");
  334. RRETURN(E_FAIL);
  335. }
  336. RRETURN(ADsAllocString( ADsClass, pADsClass));
  337. }
  338. HRESULT
  339. MakeUncName(
  340. LPWSTR szSrcBuffer,
  341. LPWSTR szTargBuffer
  342. )
  343. {
  344. ADsAssert(szSrcBuffer && *szSrcBuffer);
  345. wcscpy(szTargBuffer, L"\\\\");
  346. wcscat(szTargBuffer, szSrcBuffer);
  347. RRETURN(S_OK);
  348. }
  349. HRESULT
  350. ValidateOutParameter(
  351. BSTR * retval
  352. )
  353. {
  354. if (!retval) {
  355. RRETURN(E_ADS_BAD_PARAMETER);
  356. }
  357. RRETURN(S_OK);
  358. }
  359. PKEYDATA
  360. CreateTokenList(
  361. LPWSTR pKeyData,
  362. WCHAR ch
  363. )
  364. {
  365. BOOL fQuoteMode = FALSE; // TRUE means we're processing between
  366. // quotation marks
  367. BOOL fEscaped = FALSE; // TRUE means next one char to be
  368. // processed should be treated as literal
  369. DWORD cTokens;
  370. DWORD cb;
  371. PKEYDATA pResult;
  372. LPWSTR pDest;
  373. LPWSTR psz = pKeyData;
  374. LPWSTR pszTokenStart = NULL;
  375. LPWSTR *ppToken;
  376. if (!psz || !*psz)
  377. return NULL;
  378. cTokens=1;
  379. // Scan through the string looking for delimiters,
  380. // ensuring that each is followed by a non-NULL character:
  381. // If this char follows an unescaped backslash:
  382. // Treat as literal, treat next char regularly (set fEscaped = FALSE)
  383. // Else, if we're between quotation marks:
  384. // If we see a quotation mark, leave quote mode
  385. // Else, treat as literal
  386. // Else, if we're not between quote marks, and we see a quote mark:
  387. // Enter quote mode
  388. // Else, if we see a backslash (and we're not already in escape or quote
  389. // mode:
  390. // Treat next char as literal (set fEscaped = TRUE)
  391. // Else, if we see the delimiter, and the next char is non-NULL:
  392. // *** Found end of a token --- Increment count of tokens ***
  393. // Else:
  394. // Do nothing, just a plain old character
  395. // Go on to next character, and repeat
  396. //
  397. // Backslashes inside quotation marks are always treated as literals,
  398. // since that is the definition of being inside quotation marks
  399. while (*psz) {
  400. if (fEscaped) {
  401. fEscaped = FALSE;
  402. }
  403. else if (fQuoteMode) {
  404. if (*psz == L'"') {
  405. fQuoteMode = FALSE;
  406. }
  407. // else, do nothing, no delimiter since in quote mode
  408. }
  409. else if (*psz == L'"') {
  410. fQuoteMode = TRUE;
  411. }
  412. else if (*psz == L'\\') {
  413. fEscaped = TRUE;
  414. }
  415. else if ( (*psz == ch) && (*(psz+1))) {
  416. cTokens++;
  417. }
  418. // else, do nothing, just a regular character
  419. psz++;
  420. }
  421. cb = sizeof(KEYDATA) + (cTokens-1) * sizeof(LPWSTR) +
  422. wcslen(pKeyData)*sizeof(WCHAR) + sizeof(WCHAR);
  423. if (!(pResult = (PKEYDATA)AllocADsMem(cb)))
  424. return NULL;
  425. // Initialise pDest to point beyond the token pointers:
  426. pDest = (LPWSTR)((LPBYTE)pResult + sizeof(KEYDATA) +
  427. (cTokens-1) * sizeof(LPWSTR));
  428. // Then copy the key data buffer there:
  429. wcscpy(pDest, pKeyData);
  430. ppToken = pResult->pTokens;
  431. // Split into tokens at each delimiter be replacing the delimiter
  432. // with a NULL
  433. psz = pDest;
  434. pszTokenStart = pDest;
  435. fEscaped = FALSE;
  436. fQuoteMode = FALSE;
  437. while (*psz) {
  438. if (fEscaped) {
  439. fEscaped = FALSE;
  440. }
  441. else if (fQuoteMode) {
  442. if (*psz == L'"') {
  443. fQuoteMode = FALSE;
  444. }
  445. // else, do nothing, no delimiter since in quote mode
  446. }
  447. else if (*psz == L'"') {
  448. fQuoteMode = TRUE;
  449. }
  450. else if (*psz == L'\\') {
  451. fEscaped = TRUE;
  452. }
  453. else if ((*psz == ch) && (*(psz+1))) {
  454. *psz = '\0';
  455. *ppToken++ = pszTokenStart;
  456. pszTokenStart = psz + 1;
  457. }
  458. // else, do nothing, just a regular character
  459. psz++;
  460. }
  461. *ppToken = pszTokenStart;
  462. pResult->cTokens = cTokens;
  463. return( pResult );
  464. }
  465. HRESULT
  466. NDSConvertDWORDtoDATE(
  467. DWORD dwDate,
  468. DATE * pdaDate
  469. )
  470. {
  471. FILETIME fileTime;
  472. LARGE_INTEGER tmpTime;
  473. WORD wFatDate;
  474. WORD wFatTime;
  475. HRESULT hr = S_OK;
  476. ::RtlSecondsSince1970ToTime(dwDate, &tmpTime );
  477. fileTime.dwLowDateTime = tmpTime.LowPart;
  478. fileTime.dwHighDateTime = tmpTime.HighPart;
  479. if (!FileTimeToDosDateTime( &fileTime, &wFatDate, &wFatTime)){
  480. hr = HRESULT_FROM_WIN32(GetLastError());
  481. BAIL_ON_FAILURE(hr);
  482. }
  483. if (!DosDateTimeToVariantTime(wFatDate, wFatTime, pdaDate)){
  484. hr = HRESULT_FROM_WIN32(GetLastError());
  485. BAIL_ON_FAILURE(hr);
  486. }
  487. error:
  488. RRETURN(hr);
  489. }
  490. HRESULT
  491. NDSConvertDATEtoDWORD(
  492. DATE daDate,
  493. DWORD *pdwDate
  494. )
  495. {
  496. FILETIME fileTime;
  497. LARGE_INTEGER tmpTime;
  498. WORD wFatDate;
  499. WORD wFatTime;
  500. HRESULT hr = S_OK;
  501. if(!VariantTimeToDosDateTime(daDate, &wFatDate, &wFatTime)){
  502. hr = HRESULT_FROM_WIN32(GetLastError());
  503. BAIL_ON_FAILURE(hr);
  504. }
  505. if (!DosDateTimeToFileTime(wFatDate, wFatTime, &fileTime)) {
  506. hr = HRESULT_FROM_WIN32(GetLastError());
  507. BAIL_ON_FAILURE(hr);
  508. }
  509. tmpTime.LowPart = fileTime.dwLowDateTime;
  510. tmpTime.HighPart = fileTime.dwHighDateTime;
  511. ::RtlTimeToSecondsSince1970(&tmpTime, (ULONG *)pdwDate);
  512. error:
  513. RRETURN(hr);
  514. }
  515. DWORD
  516. ADsNwNdsOpenObject(
  517. IN LPWSTR ObjectDN,
  518. IN CCredentials& Credentials,
  519. OUT HANDLE * lphObject,
  520. OUT LPWSTR lpObjectFullName OPTIONAL,
  521. OUT LPWSTR lpObjectClassName OPTIONAL,
  522. OUT LPDWORD lpdwModificationTime,
  523. OUT LPDWORD lpdwSubordinateCount OPTIONAL
  524. )
  525. {
  526. HRESULT hr = S_OK;
  527. DWORD dwStatus = S_OK;
  528. LPWSTR pszUserName = NULL;
  529. LPWSTR pszPassword = NULL;
  530. hr = Credentials.GetUserName(&pszUserName);
  531. hr = Credentials.GetPassword(&pszPassword);
  532. // dwStatus = NwNdsOpenObject(
  533. // ObjectDN,
  534. // pszUserName,
  535. // pszPassword,
  536. // lphObject,
  537. // NULL, // szObjectName optional parameter
  538. // lpObjectFullName,
  539. // lpObjectClassName,
  540. // lpdwModificationTime,
  541. // lpdwSubordinateCount
  542. // );
  543. if (pszUserName) {
  544. FreeADsStr(pszUserName);
  545. }
  546. if (pszPassword) {
  547. FreeADsStr(pszPassword);
  548. }
  549. return(dwStatus);
  550. }
  551. HRESULT
  552. CheckAndSetExtendedError(
  553. DWORD dwRetval
  554. )
  555. {
  556. DWORD dwLastError;
  557. WCHAR pszError[MAX_PATH];
  558. WCHAR pszProviderName[MAX_PATH];
  559. INT numChars;
  560. HRESULT hr =S_OK;
  561. wcscpy(pszError, L"");
  562. wcscpy(pszProviderName, L"");
  563. if (NWCCODE_SUCCEEDED(dwRetval)){
  564. hr = S_OK;
  565. }
  566. else {
  567. if (dwRetval == ERR_NO_ACCESS) {
  568. hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  569. }
  570. else if (dwRetval == ERR_ENTRY_ALREADY_EXISTS) {
  571. hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
  572. }
  573. else if (dwRetval == ERR_NO_SUCH_ENTRY) {
  574. hr = HRESULT_FROM_WIN32(ERROR_BAD_NETPATH);
  575. }
  576. else {
  577. hr = HRESULT_FROM_WIN32(ERROR_EXTENDED_ERROR);
  578. numChars = LoadString( g_hInst,
  579. NWNDS_PROVIDER_ID,
  580. pszProviderName,
  581. MAX_PATH -1);
  582. //
  583. // Set the default error string
  584. wsprintf (pszError, L"NDS ccode = %x", dwRetval);
  585. for (DWORD i=0; i < g_cErrLookup; i++ ) {
  586. if ((DWORD) g_aErrLookup[i].errNo == dwRetval) {
  587. wcscat (pszError, L"; ");
  588. wcscat (pszError, g_aErrLookup[i].errString);
  589. break;
  590. }
  591. }
  592. ADsSetLastError(
  593. dwRetval,
  594. pszError,
  595. pszProviderName
  596. );
  597. }
  598. }
  599. RRETURN(hr);
  600. }
  601. HRESULT
  602. CopyObject(
  603. IN NDS_CONTEXT_HANDLE hDestADsContext,
  604. IN LPWSTR pszSrcADsPath,
  605. IN LPWSTR pszDestContainer,
  606. IN LPWSTR pszCommonName, //optional
  607. IN CCredentials& Credentials,
  608. OUT VOID ** ppObject
  609. )
  610. {
  611. HRESULT hr = S_OK;
  612. LPWSTR pszSrcNDSTreeName = NULL, pszSrcNDSDn = NULL;
  613. LPWSTR pszChildNDSTreeName = NULL, pszChildNDSDn = NULL;
  614. NDS_CONTEXT_HANDLE hSrcADsContext = NULL;
  615. BSTR bstrChildADsPath = NULL;
  616. NDS_BUFFER_HANDLE hDestOperationData = NULL;
  617. NDS_BUFFER_HANDLE hAttrOperationData = NULL;
  618. LPWSTR pszObjectClassName = NULL;
  619. DWORD dwNumEntries = 0L;
  620. DWORD dwNumEntriesDefs = 0L;
  621. LPNDS_ATTR_INFO lpEntries = NULL;
  622. LPWSTR pszParent= NULL;
  623. LPWSTR pszRelativeName = NULL;
  624. LPWSTR pszCN = NULL;
  625. DWORD i = 0;
  626. DWORD dwInfoType;
  627. LPNDS_ATTR_DEF lpAttrDef = NULL;
  628. IADs *pADs = NULL;
  629. LPWSTR *ppszAttrs = NULL;
  630. //
  631. // allocate all variables that are needed
  632. //
  633. pszParent = (LPWSTR)AllocADsMem(MAX_PATH* sizeof(WCHAR));
  634. if (!pszParent){
  635. hr = E_OUTOFMEMORY;
  636. goto error;
  637. }
  638. pszCN = (LPWSTR)AllocADsMem(MAX_PATH* sizeof(WCHAR));
  639. if (!pszCN){
  640. hr = E_OUTOFMEMORY;
  641. goto error;
  642. }
  643. hr = BuildADsParentPath(
  644. pszSrcADsPath,
  645. pszParent,
  646. pszCN
  647. );
  648. BAIL_ON_FAILURE(hr);
  649. hr = BuildNDSPathFromADsPath2(
  650. pszSrcADsPath,
  651. &pszSrcNDSTreeName,
  652. &pszSrcNDSDn
  653. );
  654. BAIL_ON_FAILURE(hr);
  655. hr = ADsNdsOpenContext(
  656. pszSrcNDSTreeName,
  657. Credentials,
  658. &hSrcADsContext
  659. );
  660. BAIL_ON_FAILURE(hr);
  661. hr = ADsNdsReadObject(
  662. hSrcADsContext,
  663. pszSrcNDSDn,
  664. DS_ATTRIBUTE_VALUES,
  665. NULL,
  666. (DWORD) -1, // signifies all attributes need to be returned
  667. NULL,
  668. &lpEntries,
  669. &dwNumEntries
  670. );
  671. BAIL_ON_FAILURE(hr);
  672. //
  673. // create the destination object
  674. //
  675. // use the name given by the user if given at all
  676. // otherwise use the name of the source
  677. //
  678. if ( pszCommonName != NULL) {
  679. pszRelativeName = pszCommonName;
  680. } else {
  681. pszRelativeName = pszCN;
  682. }
  683. hr = BuildADsPath(
  684. pszDestContainer,
  685. pszRelativeName,
  686. &bstrChildADsPath
  687. );
  688. BAIL_ON_FAILURE(hr);
  689. hr = BuildNDSPathFromADsPath2(
  690. bstrChildADsPath,
  691. &pszChildNDSTreeName,
  692. &pszChildNDSDn
  693. );
  694. BAIL_ON_FAILURE(hr);
  695. hr = ADsNdsCreateBuffer(
  696. hDestADsContext,
  697. DSV_ADD_ENTRY,
  698. &hDestOperationData
  699. );
  700. BAIL_ON_FAILURE(hr);
  701. ppszAttrs = (LPWSTR *) AllocADsMem(sizeof(LPWSTR) * dwNumEntries);
  702. if (!ppszAttrs) {
  703. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  704. }
  705. for(i=0; i< dwNumEntries; i++)
  706. ppszAttrs[i] = lpEntries[i].szAttributeName;
  707. hr = ADsNdsReadAttrDef(
  708. hDestADsContext,
  709. DS_ATTR_DEFS,
  710. ppszAttrs,
  711. dwNumEntries,
  712. &hAttrOperationData
  713. );
  714. BAIL_ON_FAILURE(hr);
  715. hr = ADsNdsGetAttrDefListFromBuffer(
  716. hDestADsContext,
  717. hAttrOperationData,
  718. &dwNumEntriesDefs,
  719. &dwInfoType,
  720. & lpAttrDef
  721. );
  722. BAIL_ON_FAILURE(hr);
  723. for (i=0; i< dwNumEntriesDefs; i++){
  724. if(wcscmp(lpEntries[i].szAttributeName, ACL_name) == 0){
  725. //
  726. // skip this attribute. Let it default
  727. //
  728. continue;
  729. }
  730. if(wcscmp(lpEntries[i].szAttributeName, OBJECT_CLASS_name) == 0){
  731. hr = ADsNdsPutInBuffer(
  732. hDestADsContext,
  733. hDestOperationData,
  734. lpEntries[i].szAttributeName,
  735. lpEntries[i].dwSyntaxId,
  736. lpEntries[i].lpValue,
  737. 1,
  738. DS_ADD_ATTRIBUTE
  739. );
  740. BAIL_ON_FAILURE(hr);
  741. pszObjectClassName = lpEntries[i].lpValue ?
  742. lpEntries[i].lpValue[0].NdsValue.value_20.ClassName :
  743. NULL;
  744. } else if ( (lpAttrDef[i].dwFlags & DS_READ_ONLY_ATTR)
  745. || (lpAttrDef[i].dwFlags & DS_HIDDEN_ATTR) ){
  746. //
  747. // skip this value
  748. //
  749. continue;
  750. } else {
  751. hr = ADsNdsPutInBuffer(
  752. hDestADsContext,
  753. hDestOperationData,
  754. lpEntries[i].szAttributeName,
  755. lpEntries[i].dwSyntaxId,
  756. lpEntries[i].lpValue,
  757. lpEntries[i].dwNumberOfValues,
  758. DS_ADD_ATTRIBUTE
  759. );
  760. BAIL_ON_FAILURE(hr);
  761. }
  762. }
  763. hr = ADsNdsAddObject(
  764. hDestADsContext,
  765. pszChildNDSDn,
  766. hDestOperationData
  767. );
  768. BAIL_ON_FAILURE(hr);
  769. if (!pszObjectClassName) {
  770. BAIL_ON_FAILURE(hr = E_FAIL);
  771. }
  772. if (_wcsicmp(pszObjectClassName, L"user") == 0) {
  773. hr = ADsNdsGenObjectKey(hDestADsContext,
  774. pszChildNDSDn);
  775. BAIL_ON_FAILURE(hr);
  776. }
  777. hr = CNDSGenObject::CreateGenericObject(
  778. pszDestContainer,
  779. pszRelativeName,
  780. pszObjectClassName,
  781. Credentials,
  782. ADS_OBJECT_BOUND,
  783. IID_IADs,
  784. (void **)&pADs
  785. );
  786. BAIL_ON_FAILURE(hr);
  787. //
  788. // InstantiateDerivedObject should add-ref this pointer for us.
  789. //
  790. hr = InstantiateDerivedObject(
  791. pADs,
  792. Credentials,
  793. IID_IUnknown,
  794. ppObject
  795. );
  796. if (FAILED(hr)) {
  797. hr = pADs->QueryInterface(
  798. IID_IUnknown,
  799. ppObject
  800. );
  801. BAIL_ON_FAILURE(hr);
  802. }
  803. error:
  804. FreeADsMem(pszParent);
  805. FreeADsMem(pszCN);
  806. FreeADsStr(pszSrcNDSTreeName);
  807. FreeADsStr(pszSrcNDSDn);
  808. FreeADsStr(pszChildNDSTreeName);
  809. FreeADsStr(pszChildNDSDn);
  810. FreeADsMem(ppszAttrs);
  811. if (bstrChildADsPath) {
  812. SysFreeString(bstrChildADsPath);
  813. }
  814. if (hDestOperationData) {
  815. ADsNdsFreeBuffer(hDestOperationData);
  816. }
  817. if (hAttrOperationData) {
  818. ADsNdsFreeBuffer(hAttrOperationData);
  819. }
  820. if(hSrcADsContext){
  821. ADsNdsCloseContext(hSrcADsContext);
  822. }
  823. if (pADs){
  824. pADs->Release();
  825. }
  826. FreeNdsAttrInfo(lpEntries, dwNumEntries);
  827. ADsNdsFreeAttrDefList(lpAttrDef, dwNumEntriesDefs);
  828. RRETURN(hr);
  829. }
  830. HRESULT
  831. MoveObject(
  832. IN NDS_CONTEXT_HANDLE hDestADsContext,
  833. IN LPWSTR pszSrcADsPath,
  834. IN LPWSTR pszDestContainer,
  835. IN LPWSTR pszCommonName, //optional
  836. IN CCredentials& Credentials,
  837. OUT VOID ** ppObject
  838. )
  839. {
  840. HRESULT hr = S_OK;
  841. LPWSTR pszSrcNDSTreeName = NULL, pszSrcNDSDn = NULL;
  842. LPWSTR pszParentNDSTreeName = NULL, pszParentNDSDn = NULL;
  843. NDS_CONTEXT_HANDLE hSrcADsContext = NULL;
  844. LPWSTR pszObjectClassName = NULL;
  845. DWORD dwNumEntries = 0L;
  846. LPNDS_ATTR_INFO lpEntries = NULL;
  847. LPWSTR pszParent= NULL;
  848. LPWSTR pszRelativeName = NULL;
  849. LPWSTR pszCN = NULL;
  850. IADs *pADs = NULL;
  851. LPWSTR pszAttrs = L"object Class";
  852. //
  853. // allocate all variables that are needed
  854. //
  855. pszParent = (LPWSTR)AllocADsMem(MAX_PATH* sizeof(WCHAR));
  856. if (!pszParent){
  857. hr = E_OUTOFMEMORY;
  858. goto error;
  859. }
  860. pszCN = (LPWSTR)AllocADsMem(MAX_PATH* sizeof(WCHAR));
  861. if (!pszCN){
  862. hr = E_OUTOFMEMORY;
  863. goto error;
  864. }
  865. hr = BuildADsParentPath(
  866. pszSrcADsPath,
  867. pszParent,
  868. pszCN
  869. );
  870. BAIL_ON_FAILURE(hr);
  871. hr = BuildNDSPathFromADsPath2(
  872. pszSrcADsPath,
  873. &pszSrcNDSTreeName,
  874. &pszSrcNDSDn
  875. );
  876. BAIL_ON_FAILURE(hr);
  877. hr = ADsNdsOpenContext(
  878. pszSrcNDSTreeName,
  879. Credentials,
  880. &hSrcADsContext
  881. );
  882. BAIL_ON_FAILURE(hr);
  883. //
  884. // Just get the objectClass attribute
  885. //
  886. hr = ADsNdsReadObject(
  887. hSrcADsContext,
  888. pszSrcNDSDn,
  889. DS_ATTRIBUTE_VALUES,
  890. &pszAttrs,
  891. 1,
  892. NULL,
  893. &lpEntries,
  894. &dwNumEntries
  895. );
  896. BAIL_ON_FAILURE(hr);
  897. if (dwNumEntries != 1) {
  898. BAIL_ON_FAILURE(hr = E_FAIL);
  899. }
  900. pszObjectClassName = (lpEntries[0].lpValue) ?
  901. lpEntries[0].lpValue[0].NdsValue.value_20.ClassName :
  902. NULL;
  903. if (!pszObjectClassName) {
  904. BAIL_ON_FAILURE(E_FAIL);
  905. }
  906. hr = BuildNDSPathFromADsPath2(
  907. pszDestContainer,
  908. &pszParentNDSTreeName,
  909. &pszParentNDSDn
  910. );
  911. BAIL_ON_FAILURE(hr);
  912. //
  913. // use the name given by the user if given at all
  914. // otherwise use the name of the source
  915. //
  916. if ( pszCommonName != NULL) {
  917. pszRelativeName = pszCommonName;
  918. } else {
  919. pszRelativeName = pszCN;
  920. }
  921. //
  922. // If the relative name has changed and parent hasn't changed, just do a
  923. // simple rename
  924. //
  925. if ((_wcsicmp(pszParent,pszDestContainer) == 0) &&
  926. (_wcsicmp(pszCN,pszRelativeName) != 0)) {
  927. hr = ADsNdsRenameObject(
  928. hDestADsContext,
  929. pszSrcNDSDn,
  930. pszRelativeName
  931. );
  932. BAIL_ON_FAILURE(hr);
  933. }
  934. //
  935. // If the parent has changed
  936. //
  937. if (_wcsicmp(pszParent,pszDestContainer) != 0) {
  938. hr = ADsNdsMoveObject(
  939. hDestADsContext,
  940. pszSrcNDSDn,
  941. pszParentNDSDn,
  942. pszRelativeName
  943. );
  944. BAIL_ON_FAILURE(hr);
  945. }
  946. if (!pszObjectClassName) {
  947. BAIL_ON_FAILURE(hr = E_FAIL);
  948. }
  949. hr = CNDSGenObject::CreateGenericObject(
  950. pszDestContainer,
  951. pszRelativeName,
  952. pszObjectClassName,
  953. Credentials,
  954. ADS_OBJECT_BOUND,
  955. IID_IADs,
  956. (void **)&pADs
  957. );
  958. BAIL_ON_FAILURE(hr);
  959. //
  960. // InstantiateDerivedObject should add-ref this pointer for us.
  961. //
  962. hr = InstantiateDerivedObject(
  963. pADs,
  964. Credentials,
  965. IID_IUnknown,
  966. ppObject
  967. );
  968. if (FAILED(hr)) {
  969. hr = pADs->QueryInterface(
  970. IID_IUnknown,
  971. ppObject
  972. );
  973. BAIL_ON_FAILURE(hr);
  974. }
  975. error:
  976. FreeADsMem(pszParent);
  977. FreeADsMem(pszCN);
  978. FreeADsStr(pszSrcNDSTreeName);
  979. FreeADsStr(pszSrcNDSDn);
  980. FreeADsStr(pszParentNDSTreeName);
  981. FreeADsStr(pszParentNDSDn);
  982. if(hSrcADsContext){
  983. ADsNdsCloseContext(hSrcADsContext);
  984. }
  985. if (pADs){
  986. pADs->Release();
  987. }
  988. FreeNdsAttrInfo( lpEntries, dwNumEntries );
  989. RRETURN(hr);
  990. }
  991. HRESULT
  992. ConvertDWORDtoSYSTEMTIME(
  993. DWORD dwDate,
  994. LPSYSTEMTIME pSystemTime
  995. )
  996. {
  997. FILETIME fileTime;
  998. LARGE_INTEGER tmpTime;
  999. HRESULT hr = S_OK;
  1000. ::RtlSecondsSince1970ToTime(dwDate, &tmpTime );
  1001. fileTime.dwLowDateTime = tmpTime.LowPart;
  1002. fileTime.dwHighDateTime = tmpTime.HighPart;
  1003. if (!FileTimeToSystemTime( &fileTime, pSystemTime)){
  1004. hr = HRESULT_FROM_WIN32(GetLastError());
  1005. }
  1006. RRETURN(hr);
  1007. }
  1008. HRESULT
  1009. ConvertSYSTEMTIMEtoDWORD(
  1010. CONST SYSTEMTIME *pSystemTime,
  1011. DWORD *pdwDate
  1012. )
  1013. {
  1014. FILETIME fileTime;
  1015. LARGE_INTEGER tmpTime;
  1016. HRESULT hr = S_OK;
  1017. if (!SystemTimeToFileTime(pSystemTime,&fileTime)) {
  1018. hr = HRESULT_FROM_WIN32(GetLastError());
  1019. BAIL_ON_FAILURE(hr);
  1020. }
  1021. tmpTime.LowPart = fileTime.dwLowDateTime;
  1022. tmpTime.HighPart = fileTime.dwHighDateTime;
  1023. ::RtlTimeToSecondsSince1970(&tmpTime, (ULONG *)pdwDate);
  1024. error:
  1025. RRETURN(hr);
  1026. }
  1027. HRESULT
  1028. InitializeNWLibrary(
  1029. void
  1030. )
  1031. {
  1032. NWDSCCODE ccode;
  1033. HRESULT hr = S_OK;
  1034. LCONV lConvInfo;
  1035. ccode = NWCallsInit(NULL, NULL);
  1036. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1037. ccode = NWCLXInit(NULL, NULL);
  1038. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1039. NWLlocaleconv(&lConvInfo);
  1040. ccode = NWInitUnicodeTables(lConvInfo.country_id,lConvInfo.code_page);
  1041. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1042. error:
  1043. RRETURN(hr);
  1044. }