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.

793 lines
18 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. //+------------------------------------------------------------------------
  26. //
  27. // Class: Common
  28. //
  29. // Purpose: Contains Winnt routines and properties that are common to
  30. // all Winnt objects. Winnt objects get the routines and
  31. // properties through C++ inheritance.
  32. //
  33. //-------------------------------------------------------------------------
  34. HRESULT
  35. BuildADsPath(
  36. BSTR Parent,
  37. BSTR Name,
  38. BSTR *pADsPath
  39. )
  40. {
  41. LPWSTR lpADsPath = NULL;
  42. WCHAR ProviderName[MAX_PATH];
  43. HRESULT hr = S_OK;
  44. DWORD dwLen = 0;
  45. LPWSTR pszDisplayName = NULL;
  46. //
  47. // We will assert if bad parameters are passed to us.
  48. // This is because this should never be the case. This
  49. // is an internal call
  50. //
  51. ADsAssert(Parent && Name);
  52. ADsAssert(pADsPath);
  53. if ((!Name) || (!Parent) || (!pADsPath)) {
  54. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  55. }
  56. //
  57. // Get the display name for the name; The display name will have the proper
  58. // escaping for characters that have special meaning in an ADsPath like
  59. // '/' etc.
  60. //
  61. hr = GetDisplayName(
  62. Name,
  63. &pszDisplayName
  64. );
  65. BAIL_ON_FAILURE(hr);
  66. //
  67. // Special case the Namespace object; if
  68. // the parent is L"ADs:", then Name = ADsPath
  69. //
  70. if (!_wcsicmp(Parent, L"ADs:")) {
  71. hr = ADsAllocString( pszDisplayName, pADsPath);
  72. BAIL_ON_FAILURE(hr);
  73. goto cleanup;
  74. }
  75. //
  76. // Allocate the right side buffer
  77. // 2 for // + a buffer of MAX_PATH
  78. //
  79. dwLen = wcslen(Parent) + wcslen(pszDisplayName) + 2 + MAX_PATH;
  80. lpADsPath = (LPWSTR)AllocADsMem(dwLen*sizeof(WCHAR));
  81. if (!lpADsPath) {
  82. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  83. }
  84. //
  85. // The rest of the cases we expect valid data,
  86. // Path, Parent and Name are read-only, the end-user
  87. // cannot modify this data
  88. //
  89. //
  90. // For the first object, the domain object we do not add
  91. // the first backslash; so we examine that the parent is
  92. // L"WinNT:" and skip the slash otherwise we start with
  93. // the slash
  94. //
  95. wsprintf(ProviderName, L"%s:", szProviderName);
  96. wcscpy(lpADsPath, Parent);
  97. if (_wcsicmp(lpADsPath, ProviderName)) {
  98. wcscat(lpADsPath, L"/");
  99. }else {
  100. wcscat(lpADsPath, L"//");
  101. }
  102. wcscat(lpADsPath, pszDisplayName);
  103. hr = ADsAllocString( lpADsPath, pADsPath);
  104. cleanup:
  105. error:
  106. if (lpADsPath) {
  107. FreeADsMem(lpADsPath);
  108. }
  109. if (pszDisplayName) {
  110. FreeADsMem(pszDisplayName);
  111. }
  112. RRETURN(hr);
  113. }
  114. HRESULT
  115. BuildSchemaPath(
  116. BSTR bstrADsPath,
  117. BSTR bstrClass,
  118. BSTR *pSchemaPath
  119. )
  120. {
  121. WCHAR ADsSchema[MAX_PATH];
  122. OBJECTINFO ObjectInfo;
  123. POBJECTINFO pObjectInfo = &ObjectInfo;
  124. CLexer Lexer(bstrADsPath);
  125. HRESULT hr = S_OK;
  126. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  127. wcscpy(ADsSchema, L"");
  128. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  129. if (bstrClass && *bstrClass) {
  130. hr = ADsObject(&Lexer, pObjectInfo);
  131. BAIL_ON_FAILURE(hr);
  132. if (pObjectInfo->TreeName) {
  133. wsprintf(ADsSchema,L"%s://",pObjectInfo->ProviderName);
  134. wcscat(ADsSchema, pObjectInfo->TreeName);
  135. wcscat(ADsSchema,L"/schema/");
  136. wcscat(ADsSchema, bstrClass);
  137. }
  138. }
  139. hr = ADsAllocString( ADsSchema, pSchemaPath);
  140. error:
  141. if (pObjectInfo) {
  142. FreeObjectInfo( pObjectInfo );
  143. }
  144. RRETURN(hr);
  145. }
  146. HRESULT
  147. BuildADsGuid(
  148. REFCLSID clsid,
  149. BSTR *pADsClass
  150. )
  151. {
  152. WCHAR ADsClass[MAX_PATH];
  153. if (!StringFromGUID2(clsid, ADsClass, MAX_PATH)) {
  154. //
  155. // MAX_PATH should be more than enough for the GUID.
  156. //
  157. ADsAssert(!"GUID too big !!!");
  158. RRETURN(E_FAIL);
  159. }
  160. RRETURN(ADsAllocString( ADsClass, pADsClass));
  161. }
  162. HRESULT
  163. MakeUncName(
  164. LPWSTR szSrcBuffer,
  165. LPWSTR szTargBuffer
  166. )
  167. {
  168. ADsAssert(szSrcBuffer && *szSrcBuffer);
  169. wcscpy(szTargBuffer, L"\\\\");
  170. wcscat(szTargBuffer, szSrcBuffer);
  171. RRETURN(S_OK);
  172. }
  173. HRESULT
  174. ValidateOutParameter(
  175. BSTR * retval
  176. )
  177. {
  178. if (!retval) {
  179. RRETURN(E_ADS_BAD_PARAMETER);
  180. }
  181. RRETURN(S_OK);
  182. }
  183. PKEYDATA
  184. CreateTokenList(
  185. LPWSTR pKeyData,
  186. WCHAR ch
  187. )
  188. {
  189. DWORD cTokens;
  190. DWORD cb;
  191. PKEYDATA pResult;
  192. LPWSTR pDest;
  193. LPWSTR psz = pKeyData;
  194. LPWSTR *ppToken;
  195. WCHAR szTokenList[MAX_PATH];
  196. if (!psz || !*psz)
  197. return NULL;
  198. wsprintf(szTokenList, L"%c", ch);
  199. cTokens=1;
  200. // Scan through the string looking for commas,
  201. // ensuring that each is followed by a non-NULL character:
  202. while ((psz = wcschr(psz, ch)) && psz[1]) {
  203. cTokens++;
  204. psz++;
  205. }
  206. cb = sizeof(KEYDATA) + (cTokens-1) * sizeof(LPWSTR) +
  207. wcslen(pKeyData)*sizeof(WCHAR) + sizeof(WCHAR);
  208. if (!(pResult = (PKEYDATA)AllocADsMem(cb)))
  209. return NULL;
  210. // Initialise pDest to point beyond the token pointers:
  211. pDest = (LPWSTR)((LPBYTE)pResult + sizeof(KEYDATA) +
  212. (cTokens-1) * sizeof(LPWSTR));
  213. // Then copy the key data buffer there:
  214. wcscpy(pDest, pKeyData);
  215. ppToken = pResult->pTokens;
  216. // Remember, wcstok has the side effect of replacing the delimiter
  217. // by NULL, which is precisely what we want:
  218. psz = wcstok (pDest, szTokenList);
  219. while (psz) {
  220. *ppToken++ = psz;
  221. psz = wcstok (NULL, szTokenList);
  222. }
  223. pResult->cTokens = cTokens;
  224. return( pResult );
  225. }
  226. DWORD
  227. ADsNwNdsOpenObject(
  228. IN LPWSTR ObjectDN,
  229. IN CCredentials& Credentials,
  230. OUT HANDLE * lphObject,
  231. OUT LPWSTR lpObjectFullName OPTIONAL,
  232. OUT LPWSTR lpObjectClassName OPTIONAL,
  233. OUT LPDWORD lpdwModificationTime,
  234. OUT LPDWORD lpdwSubordinateCount OPTIONAL
  235. )
  236. {
  237. HRESULT hr = S_OK;
  238. DWORD dwStatus;
  239. LPWSTR pszUserName = NULL;
  240. LPWSTR pszPassword = NULL;
  241. hr = Credentials.GetUserName(&pszUserName);
  242. hr = Credentials.GetPassword(&pszPassword);
  243. dwStatus = NwNdsOpenObject(
  244. ObjectDN,
  245. pszUserName,
  246. pszPassword,
  247. lphObject,
  248. NULL, // szObjectName optional parameter
  249. lpObjectFullName,
  250. lpObjectClassName,
  251. lpdwModificationTime,
  252. lpdwSubordinateCount
  253. );
  254. if (pszUserName) {
  255. FreeADsStr(pszUserName);
  256. }
  257. if (pszPassword) {
  258. FreeADsStr(pszPassword);
  259. }
  260. return(dwStatus);
  261. }
  262. HRESULT
  263. CheckAndSetExtendedError(
  264. DWORD dwRetval
  265. )
  266. {
  267. DWORD dwLastError;
  268. WCHAR pszErrorString[MAX_PATH];
  269. WCHAR pszProviderName[MAX_PATH];
  270. INT numChars;
  271. HRESULT hr =S_OK;
  272. wcscpy(pszErrorString, L"");
  273. wcscpy(pszProviderName, L"");
  274. if (dwRetval == NDS_ERR_SUCCESS){
  275. hr = S_OK;
  276. } else {
  277. dwLastError = GetLastError();
  278. hr = HRESULT_FROM_WIN32(dwLastError);
  279. if (dwLastError == ERROR_EXTENDED_ERROR){
  280. numChars = LoadString( g_hInst,
  281. dwRetval,
  282. pszErrorString,
  283. MAX_PATH-1);
  284. numChars = LoadString( g_hInst,
  285. NDS_PROVIDER_ID,
  286. pszProviderName,
  287. MAX_PATH -1);
  288. ADsSetLastError( dwRetval,
  289. pszErrorString,
  290. pszProviderName );
  291. }
  292. }
  293. RRETURN(hr);
  294. }
  295. HRESULT
  296. CopyObject(
  297. IN LPWSTR pszSrcADsPath,
  298. IN LPWSTR pszDestContainer,
  299. IN LPWSTR pszCommonName, //optional
  300. IN CCredentials Credentials,
  301. OUT VOID ** ppObject
  302. )
  303. {
  304. //
  305. // this function is a wrapper for the copy functionality which is used
  306. // by both IADsContainer::CopyHere and IADsContainer::MoveHere
  307. //
  308. HRESULT hr = S_OK;
  309. DWORD dwStatus = 0L;
  310. LPWSTR pszNDSSrcName = NULL;
  311. LPWSTR pszNDSParentName = NULL;
  312. HANDLE hSrcOperationData = NULL;
  313. HANDLE hSrcObject = NULL;
  314. HANDLE hDestOperationData = NULL;
  315. HANDLE hDestObject = NULL;
  316. HANDLE hAttrOperationData = NULL;
  317. DWORD dwNumEntries = 0L;
  318. LPNDS_ATTR_INFO lpEntries = NULL;
  319. LPWSTR pszObjectFullName= NULL;
  320. LPWSTR pszObjectClassName= NULL;
  321. LPWSTR pszParent= NULL;
  322. LPWSTR pszRelativeName = NULL;
  323. LPWSTR pszCN = NULL;
  324. DWORD i = 0;
  325. DWORD dwInfoType;
  326. LPNDS_ATTR_DEF lpAttrDef = NULL;
  327. IADs *pADs = NULL;
  328. //
  329. // allocate all variables that are needed
  330. //
  331. pszObjectFullName = (LPWSTR)AllocADsMem(MAX_PATH* sizeof(WCHAR));
  332. if (!pszObjectFullName){
  333. hr = E_OUTOFMEMORY;
  334. goto error;
  335. }
  336. pszObjectClassName = (LPWSTR)AllocADsMem(MAX_PATH* sizeof(WCHAR));
  337. if (!pszObjectClassName){
  338. hr = E_OUTOFMEMORY;
  339. goto error;
  340. }
  341. pszParent = (LPWSTR)AllocADsMem(MAX_PATH* sizeof(WCHAR));
  342. if (!pszParent){
  343. hr = E_OUTOFMEMORY;
  344. goto error;
  345. }
  346. pszCN = (LPWSTR)AllocADsMem(MAX_PATH* sizeof(WCHAR));
  347. if (!pszCN){
  348. hr = E_OUTOFMEMORY;
  349. goto error;
  350. }
  351. hr = BuildNDSPathFromADsPath(
  352. pszSrcADsPath,
  353. &pszNDSSrcName
  354. );
  355. BAIL_ON_FAILURE(hr);
  356. hr = BuildADsParentPath(
  357. pszSrcADsPath,
  358. pszParent,
  359. pszCN
  360. );
  361. BAIL_ON_FAILURE(hr);
  362. dwStatus = ADsNwNdsOpenObject(
  363. pszNDSSrcName,
  364. Credentials,
  365. &hSrcObject,
  366. pszObjectFullName,
  367. pszObjectClassName,
  368. NULL,
  369. NULL
  370. );
  371. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  372. dwStatus = NwNdsReadObject(
  373. hSrcObject,
  374. NDS_INFO_ATTR_NAMES_VALUES,
  375. &hSrcOperationData
  376. );
  377. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  378. dwStatus = NwNdsGetAttrListFromBuffer(
  379. hSrcOperationData,
  380. &dwNumEntries,
  381. &lpEntries
  382. );
  383. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  384. //
  385. // we have now extracted all the information we need from the source
  386. // object, we need to add this information to the destination object
  387. // as attributes and values
  388. //
  389. //
  390. // create the destination object
  391. //
  392. hr = BuildNDSPathFromADsPath(
  393. pszDestContainer,
  394. &pszNDSParentName
  395. );
  396. BAIL_ON_FAILURE(hr);
  397. dwStatus = ADsNwNdsOpenObject(
  398. pszNDSParentName,
  399. Credentials,
  400. &hDestObject,
  401. NULL,
  402. NULL,
  403. NULL,
  404. NULL
  405. );
  406. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  407. //
  408. // use the name given by the user if given at all
  409. // otherwise use the name of the source
  410. //
  411. if ( pszCommonName != NULL) {
  412. pszRelativeName = pszCommonName;
  413. } else {
  414. pszRelativeName = pszCN;
  415. }
  416. dwStatus = NwNdsCreateBuffer(
  417. NDS_OBJECT_ADD,
  418. &hDestOperationData
  419. );
  420. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  421. //
  422. // take each of these entries and get back their schema
  423. // attribute definitions. the same handle to the DestObject
  424. // can be used to open the schema
  425. //
  426. dwStatus = NwNdsCreateBuffer(
  427. NDS_SCHEMA_READ_ATTR_DEF,
  428. &hAttrOperationData
  429. );
  430. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  431. for(i=0; i< dwNumEntries; i++){
  432. dwStatus = NwNdsPutInBuffer(
  433. lpEntries[i].szAttributeName,
  434. 0,
  435. NULL,
  436. 0,
  437. 0,
  438. hAttrOperationData
  439. );
  440. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  441. }
  442. dwStatus = NwNdsReadAttrDef(
  443. hDestObject,
  444. NDS_INFO_NAMES_DEFS,
  445. & hAttrOperationData
  446. );
  447. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  448. dwStatus = NwNdsGetAttrDefListFromBuffer(
  449. hAttrOperationData,
  450. & dwNumEntries,
  451. & dwInfoType,
  452. (void **)& lpAttrDef
  453. );
  454. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  455. for (i=0; i< dwNumEntries; i++){
  456. if(wcscmp(lpEntries[i].szAttributeName, ACL_name) == 0){
  457. //
  458. // skip this attribute. Let it default
  459. //
  460. continue;
  461. }
  462. if(wcscmp(lpEntries[i].szAttributeName, OBJECT_CLASS_name) == 0){
  463. dwStatus = NwNdsPutInBuffer(
  464. lpEntries[i].szAttributeName,
  465. lpEntries[i].dwSyntaxId,
  466. lpEntries[i].lpValue,
  467. 1, // only the first value is relevant
  468. NDS_ATTR_ADD,
  469. hDestOperationData
  470. );
  471. } else if ( (lpAttrDef[i].dwFlags & NDS_READ_ONLY_ATTR)
  472. || (lpAttrDef[i].dwFlags & NDS_HIDDEN_ATTR) ){
  473. //
  474. // skip this value
  475. //
  476. continue;
  477. } else {
  478. dwStatus = NwNdsPutInBuffer(
  479. lpEntries[i].szAttributeName,
  480. lpEntries[i].dwSyntaxId,
  481. lpEntries[i].lpValue,
  482. lpEntries[i].dwNumberOfValues,
  483. NDS_ATTR_ADD,
  484. hDestOperationData
  485. );
  486. }
  487. }
  488. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  489. dwStatus = NwNdsAddObject(
  490. hDestObject,
  491. pszRelativeName,
  492. hDestOperationData
  493. );
  494. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  495. hr = CNDSGenObject::CreateGenericObject(
  496. pszDestContainer,
  497. pszRelativeName,
  498. pszObjectClassName,
  499. Credentials,
  500. ADS_OBJECT_BOUND,
  501. IID_IADs,
  502. (void **)&pADs
  503. );
  504. BAIL_ON_FAILURE(hr);
  505. //
  506. // InstantiateDerivedObject should add-ref this pointer for us.
  507. //
  508. hr = InstantiateDerivedObject(
  509. pADs,
  510. Credentials,
  511. IID_IUnknown,
  512. ppObject
  513. );
  514. if (FAILED(hr)) {
  515. hr = pADs->QueryInterface(
  516. IID_IUnknown,
  517. ppObject
  518. );
  519. BAIL_ON_FAILURE(hr);
  520. }
  521. error:
  522. if (pszObjectFullName){
  523. FreeADsMem(pszObjectFullName);
  524. }
  525. if (pszObjectClassName){
  526. FreeADsMem(pszObjectClassName);
  527. }
  528. if (pszParent){
  529. FreeADsMem(pszParent);
  530. }
  531. if (pszCN){
  532. FreeADsMem(pszCN);
  533. }
  534. if (pszNDSSrcName) {
  535. FreeADsStr(pszNDSSrcName);
  536. }
  537. if (pszNDSParentName) {
  538. FreeADsStr(pszNDSParentName);
  539. }
  540. if(hSrcOperationData){
  541. dwStatus = NwNdsFreeBuffer(hSrcOperationData);
  542. }
  543. if(hSrcObject){
  544. dwStatus = NwNdsCloseObject(hSrcObject);
  545. }
  546. if(hDestOperationData){
  547. dwStatus = NwNdsFreeBuffer(hDestOperationData);
  548. }
  549. if(hDestObject){
  550. dwStatus = NwNdsCloseObject(hDestObject);
  551. }
  552. if(hAttrOperationData){
  553. dwStatus = NwNdsFreeBuffer(hAttrOperationData);
  554. }
  555. if (pADs){
  556. pADs->Release();
  557. }
  558. RRETURN(hr);
  559. }
  560. HRESULT
  561. ConvertDWORDtoSYSTEMTIME(
  562. DWORD dwDate,
  563. LPSYSTEMTIME pSystemTime
  564. )
  565. {
  566. FILETIME fileTime;
  567. LARGE_INTEGER tmpTime;
  568. HRESULT hr = S_OK;
  569. ::RtlSecondsSince1970ToTime(dwDate, &tmpTime );
  570. fileTime.dwLowDateTime = tmpTime.LowPart;
  571. fileTime.dwHighDateTime = tmpTime.HighPart;
  572. if (!FileTimeToSystemTime( &fileTime, pSystemTime)){
  573. hr = HRESULT_FROM_WIN32(GetLastError());
  574. }
  575. RRETURN(hr);
  576. }
  577. HRESULT
  578. ConvertSYSTEMTIMEtoDWORD(
  579. CONST SYSTEMTIME *pSystemTime,
  580. DWORD *pdwDate
  581. )
  582. {
  583. FILETIME fileTime;
  584. LARGE_INTEGER tmpTime;
  585. HRESULT hr = S_OK;
  586. if (!SystemTimeToFileTime(pSystemTime,&fileTime)) {
  587. hr = HRESULT_FROM_WIN32(GetLastError());
  588. BAIL_ON_FAILURE(hr);
  589. }
  590. tmpTime.LowPart = fileTime.dwLowDateTime;
  591. tmpTime.HighPart = fileTime.dwHighDateTime;
  592. ::RtlTimeToSecondsSince1970(&tmpTime, (ULONG *)pdwDate);
  593. error:
  594. RRETURN(hr);
  595. }