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.

794 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. SecureZeroMemory(pszPassword, wcslen(pszPassword)*sizeof(WCHAR));
  259. FreeADsStr(pszPassword);
  260. }
  261. return(dwStatus);
  262. }
  263. HRESULT
  264. CheckAndSetExtendedError(
  265. DWORD dwRetval
  266. )
  267. {
  268. DWORD dwLastError;
  269. WCHAR pszErrorString[MAX_PATH];
  270. WCHAR pszProviderName[MAX_PATH];
  271. INT numChars;
  272. HRESULT hr =S_OK;
  273. wcscpy(pszErrorString, L"");
  274. wcscpy(pszProviderName, L"");
  275. if (dwRetval == NDS_ERR_SUCCESS){
  276. hr = S_OK;
  277. } else {
  278. dwLastError = GetLastError();
  279. hr = HRESULT_FROM_WIN32(dwLastError);
  280. if (dwLastError == ERROR_EXTENDED_ERROR){
  281. numChars = LoadString( g_hInst,
  282. dwRetval,
  283. pszErrorString,
  284. MAX_PATH-1);
  285. numChars = LoadString( g_hInst,
  286. NDS_PROVIDER_ID,
  287. pszProviderName,
  288. MAX_PATH -1);
  289. ADsSetLastError( dwRetval,
  290. pszErrorString,
  291. pszProviderName );
  292. }
  293. }
  294. RRETURN(hr);
  295. }
  296. HRESULT
  297. CopyObject(
  298. IN LPWSTR pszSrcADsPath,
  299. IN LPWSTR pszDestContainer,
  300. IN LPWSTR pszCommonName, //optional
  301. IN CCredentials Credentials,
  302. OUT VOID ** ppObject
  303. )
  304. {
  305. //
  306. // this function is a wrapper for the copy functionality which is used
  307. // by both IADsContainer::CopyHere and IADsContainer::MoveHere
  308. //
  309. HRESULT hr = S_OK;
  310. DWORD dwStatus = 0L;
  311. LPWSTR pszNDSSrcName = NULL;
  312. LPWSTR pszNDSParentName = NULL;
  313. HANDLE hSrcOperationData = NULL;
  314. HANDLE hSrcObject = NULL;
  315. HANDLE hDestOperationData = NULL;
  316. HANDLE hDestObject = NULL;
  317. HANDLE hAttrOperationData = NULL;
  318. DWORD dwNumEntries = 0L;
  319. LPNDS_ATTR_INFO lpEntries = NULL;
  320. LPWSTR pszObjectFullName= NULL;
  321. LPWSTR pszObjectClassName= NULL;
  322. LPWSTR pszParent= NULL;
  323. LPWSTR pszRelativeName = NULL;
  324. LPWSTR pszCN = NULL;
  325. DWORD i = 0;
  326. DWORD dwInfoType;
  327. LPNDS_ATTR_DEF lpAttrDef = NULL;
  328. IADs *pADs = NULL;
  329. //
  330. // allocate all variables that are needed
  331. //
  332. pszObjectFullName = (LPWSTR)AllocADsMem(MAX_PATH* sizeof(WCHAR));
  333. if (!pszObjectFullName){
  334. hr = E_OUTOFMEMORY;
  335. goto error;
  336. }
  337. pszObjectClassName = (LPWSTR)AllocADsMem(MAX_PATH* sizeof(WCHAR));
  338. if (!pszObjectClassName){
  339. hr = E_OUTOFMEMORY;
  340. goto error;
  341. }
  342. pszParent = (LPWSTR)AllocADsMem(MAX_PATH* sizeof(WCHAR));
  343. if (!pszParent){
  344. hr = E_OUTOFMEMORY;
  345. goto error;
  346. }
  347. pszCN = (LPWSTR)AllocADsMem(MAX_PATH* sizeof(WCHAR));
  348. if (!pszCN){
  349. hr = E_OUTOFMEMORY;
  350. goto error;
  351. }
  352. hr = BuildNDSPathFromADsPath(
  353. pszSrcADsPath,
  354. &pszNDSSrcName
  355. );
  356. BAIL_ON_FAILURE(hr);
  357. hr = BuildADsParentPath(
  358. pszSrcADsPath,
  359. pszParent,
  360. pszCN
  361. );
  362. BAIL_ON_FAILURE(hr);
  363. dwStatus = ADsNwNdsOpenObject(
  364. pszNDSSrcName,
  365. Credentials,
  366. &hSrcObject,
  367. pszObjectFullName,
  368. pszObjectClassName,
  369. NULL,
  370. NULL
  371. );
  372. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  373. dwStatus = NwNdsReadObject(
  374. hSrcObject,
  375. NDS_INFO_ATTR_NAMES_VALUES,
  376. &hSrcOperationData
  377. );
  378. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  379. dwStatus = NwNdsGetAttrListFromBuffer(
  380. hSrcOperationData,
  381. &dwNumEntries,
  382. &lpEntries
  383. );
  384. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  385. //
  386. // we have now extracted all the information we need from the source
  387. // object, we need to add this information to the destination object
  388. // as attributes and values
  389. //
  390. //
  391. // create the destination object
  392. //
  393. hr = BuildNDSPathFromADsPath(
  394. pszDestContainer,
  395. &pszNDSParentName
  396. );
  397. BAIL_ON_FAILURE(hr);
  398. dwStatus = ADsNwNdsOpenObject(
  399. pszNDSParentName,
  400. Credentials,
  401. &hDestObject,
  402. NULL,
  403. NULL,
  404. NULL,
  405. NULL
  406. );
  407. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  408. //
  409. // use the name given by the user if given at all
  410. // otherwise use the name of the source
  411. //
  412. if ( pszCommonName != NULL) {
  413. pszRelativeName = pszCommonName;
  414. } else {
  415. pszRelativeName = pszCN;
  416. }
  417. dwStatus = NwNdsCreateBuffer(
  418. NDS_OBJECT_ADD,
  419. &hDestOperationData
  420. );
  421. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  422. //
  423. // take each of these entries and get back their schema
  424. // attribute definitions. the same handle to the DestObject
  425. // can be used to open the schema
  426. //
  427. dwStatus = NwNdsCreateBuffer(
  428. NDS_SCHEMA_READ_ATTR_DEF,
  429. &hAttrOperationData
  430. );
  431. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  432. for(i=0; i< dwNumEntries; i++){
  433. dwStatus = NwNdsPutInBuffer(
  434. lpEntries[i].szAttributeName,
  435. 0,
  436. NULL,
  437. 0,
  438. 0,
  439. hAttrOperationData
  440. );
  441. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  442. }
  443. dwStatus = NwNdsReadAttrDef(
  444. hDestObject,
  445. NDS_INFO_NAMES_DEFS,
  446. & hAttrOperationData
  447. );
  448. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  449. dwStatus = NwNdsGetAttrDefListFromBuffer(
  450. hAttrOperationData,
  451. & dwNumEntries,
  452. & dwInfoType,
  453. (void **)& lpAttrDef
  454. );
  455. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  456. for (i=0; i< dwNumEntries; i++){
  457. if(wcscmp(lpEntries[i].szAttributeName, ACL_name) == 0){
  458. //
  459. // skip this attribute. Let it default
  460. //
  461. continue;
  462. }
  463. if(wcscmp(lpEntries[i].szAttributeName, OBJECT_CLASS_name) == 0){
  464. dwStatus = NwNdsPutInBuffer(
  465. lpEntries[i].szAttributeName,
  466. lpEntries[i].dwSyntaxId,
  467. lpEntries[i].lpValue,
  468. 1, // only the first value is relevant
  469. NDS_ATTR_ADD,
  470. hDestOperationData
  471. );
  472. } else if ( (lpAttrDef[i].dwFlags & NDS_READ_ONLY_ATTR)
  473. || (lpAttrDef[i].dwFlags & NDS_HIDDEN_ATTR) ){
  474. //
  475. // skip this value
  476. //
  477. continue;
  478. } else {
  479. dwStatus = NwNdsPutInBuffer(
  480. lpEntries[i].szAttributeName,
  481. lpEntries[i].dwSyntaxId,
  482. lpEntries[i].lpValue,
  483. lpEntries[i].dwNumberOfValues,
  484. NDS_ATTR_ADD,
  485. hDestOperationData
  486. );
  487. }
  488. }
  489. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  490. dwStatus = NwNdsAddObject(
  491. hDestObject,
  492. pszRelativeName,
  493. hDestOperationData
  494. );
  495. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  496. hr = CNDSGenObject::CreateGenericObject(
  497. pszDestContainer,
  498. pszRelativeName,
  499. pszObjectClassName,
  500. Credentials,
  501. ADS_OBJECT_BOUND,
  502. IID_IADs,
  503. (void **)&pADs
  504. );
  505. BAIL_ON_FAILURE(hr);
  506. //
  507. // InstantiateDerivedObject should add-ref this pointer for us.
  508. //
  509. hr = InstantiateDerivedObject(
  510. pADs,
  511. Credentials,
  512. IID_IUnknown,
  513. ppObject
  514. );
  515. if (FAILED(hr)) {
  516. hr = pADs->QueryInterface(
  517. IID_IUnknown,
  518. ppObject
  519. );
  520. BAIL_ON_FAILURE(hr);
  521. }
  522. error:
  523. if (pszObjectFullName){
  524. FreeADsMem(pszObjectFullName);
  525. }
  526. if (pszObjectClassName){
  527. FreeADsMem(pszObjectClassName);
  528. }
  529. if (pszParent){
  530. FreeADsMem(pszParent);
  531. }
  532. if (pszCN){
  533. FreeADsMem(pszCN);
  534. }
  535. if (pszNDSSrcName) {
  536. FreeADsStr(pszNDSSrcName);
  537. }
  538. if (pszNDSParentName) {
  539. FreeADsStr(pszNDSParentName);
  540. }
  541. if(hSrcOperationData){
  542. dwStatus = NwNdsFreeBuffer(hSrcOperationData);
  543. }
  544. if(hSrcObject){
  545. dwStatus = NwNdsCloseObject(hSrcObject);
  546. }
  547. if(hDestOperationData){
  548. dwStatus = NwNdsFreeBuffer(hDestOperationData);
  549. }
  550. if(hDestObject){
  551. dwStatus = NwNdsCloseObject(hDestObject);
  552. }
  553. if(hAttrOperationData){
  554. dwStatus = NwNdsFreeBuffer(hAttrOperationData);
  555. }
  556. if (pADs){
  557. pADs->Release();
  558. }
  559. RRETURN(hr);
  560. }
  561. HRESULT
  562. ConvertDWORDtoSYSTEMTIME(
  563. DWORD dwDate,
  564. LPSYSTEMTIME pSystemTime
  565. )
  566. {
  567. FILETIME fileTime;
  568. LARGE_INTEGER tmpTime;
  569. HRESULT hr = S_OK;
  570. ::RtlSecondsSince1970ToTime(dwDate, &tmpTime );
  571. fileTime.dwLowDateTime = tmpTime.LowPart;
  572. fileTime.dwHighDateTime = tmpTime.HighPart;
  573. if (!FileTimeToSystemTime( &fileTime, pSystemTime)){
  574. hr = HRESULT_FROM_WIN32(GetLastError());
  575. }
  576. RRETURN(hr);
  577. }
  578. HRESULT
  579. ConvertSYSTEMTIMEtoDWORD(
  580. CONST SYSTEMTIME *pSystemTime,
  581. DWORD *pdwDate
  582. )
  583. {
  584. FILETIME fileTime;
  585. LARGE_INTEGER tmpTime;
  586. HRESULT hr = S_OK;
  587. if (!SystemTimeToFileTime(pSystemTime,&fileTime)) {
  588. hr = HRESULT_FROM_WIN32(GetLastError());
  589. BAIL_ON_FAILURE(hr);
  590. }
  591. tmpTime.LowPart = fileTime.dwLowDateTime;
  592. tmpTime.HighPart = fileTime.dwHighDateTime;
  593. ::RtlTimeToSecondsSince1970(&tmpTime, (ULONG *)pdwDate);
  594. error:
  595. RRETURN(hr);
  596. }