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.

323 lines
7.3 KiB

  1. //--------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1999, Microsoft Corporation
  4. //
  5. // File: rootsup.cxx
  6. //
  7. //--------------------------------------------------------------------------
  8. #define UNICODE
  9. #include <stdio.h>
  10. #include <nt.h>
  11. #include <ntrtl.h>
  12. #include <nturtl.h>
  13. #include <windows.h>
  14. #include <winldap.h>
  15. #include <stdlib.h>
  16. #include <dsgetdc.h>
  17. #include <lm.h>
  18. #include <dfsstr.h>
  19. #include <lmdfs.h>
  20. #include <dfspriv.h>
  21. #include <dfsm.hxx>
  22. #include <rpc.h>
  23. #include "struct.hxx"
  24. #include "rootsup.hxx"
  25. #include "ftsup.hxx"
  26. #include "misc.hxx"
  27. #include "messages.h"
  28. DWORD
  29. NetDfsRootEnum(
  30. LPWSTR pwszDcName,
  31. LPWSTR pwszDomainName,
  32. PSEC_WINNT_AUTH_IDENTITY pAuthIdent,
  33. LPWSTR **List)
  34. {
  35. DWORD dwErr = ERROR_SUCCESS;
  36. NTSTATUS status;
  37. PWCHAR attrs[2];
  38. LDAPMessage *pMsg = NULL;
  39. LDAPMessage *pEntry = NULL;
  40. WCHAR *pAttr = NULL;
  41. WCHAR **rpValues = NULL;
  42. WCHAR **allValues = NULL;
  43. WCHAR ***rpValuesToFree = NULL;
  44. INT cValues = 0;
  45. INT i;
  46. WCHAR *dfsDn = NULL;
  47. DWORD len;
  48. PWCHAR *resultVector = NULL;
  49. PLDAP pLDAP = NULL;
  50. LPWSTR pstr;
  51. ULONG slen;
  52. if (fSwDebug)
  53. MyPrintf(L"NetDfsRootEnum(%ws,%ws)\r\n", pwszDcName, pwszDomainName);
  54. if (List == NULL) {
  55. return ERROR_INVALID_PARAMETER;
  56. }
  57. if (pwszDcName == NULL)
  58. dwErr = DfspGetPdc(wszDcName, pwszDomainName);
  59. else
  60. wcscpy(wszDcName, pwszDcName);
  61. if (dwErr != ERROR_SUCCESS)
  62. goto Cleanup;
  63. ErrorMessage(MSG_CONNECTING, wszDcName);
  64. dwErr = DfspLdapOpen(wszDcName, pAuthIdent, &pLDAP, DfsConfigContainer, &dfsDn);
  65. if (dwErr != ERROR_SUCCESS)
  66. goto Cleanup;
  67. *List = NULL;
  68. //
  69. // Now see if we can enumerate the objects below this one. The names
  70. // of these objects will be the different FT dfs's available
  71. //
  72. pLDAP->ld_sizelimit = 0;
  73. pLDAP->ld_timelimit= 0;
  74. pLDAP->ld_deref = LDAP_DEREF_NEVER;
  75. attrs[0] = L"CN";
  76. attrs[1] = NULL;
  77. dwErr = ldap_search_s(
  78. pLDAP,
  79. dfsDn,
  80. LDAP_SCOPE_ONELEVEL,
  81. L"(objectClass=fTDfs)",
  82. attrs,
  83. 0,
  84. &pMsg);
  85. //
  86. // Make sure the result is reasonable
  87. //
  88. if (
  89. ((cValues = ldap_count_entries(pLDAP, pMsg)) == 0) ||
  90. (pEntry = ldap_first_entry(pLDAP, pMsg)) == NULL
  91. ) {
  92. dwErr = ERROR_PATH_NOT_FOUND;
  93. goto Cleanup;
  94. }
  95. //
  96. // The search for all FTDfs's returns multiple entries, each with
  97. // one value for the object's CN. Coalesce these into a single array.
  98. //
  99. dwErr = NetApiBufferAllocate(2 * (cValues + 1) * sizeof(PWSTR), (PVOID *)&allValues);
  100. if (dwErr != ERROR_SUCCESS) {
  101. goto Cleanup;
  102. }
  103. rpValuesToFree = (WCHAR ***) &allValues[cValues + 1];
  104. for (i = 0; (i < cValues) && (dwErr == ERROR_SUCCESS); i++) {
  105. rpValues = ldap_get_values(pLDAP, pEntry, attrs[0]);
  106. rpValuesToFree[i] = rpValues;
  107. //
  108. // Sanity check
  109. //
  110. if (ldap_count_values(rpValues) == 0 || rpValues[0][0] == L'\0') {
  111. dwErr = ERROR_PATH_NOT_FOUND;
  112. } else {
  113. allValues[i] = rpValues[0];
  114. pEntry = ldap_next_entry(pLDAP, pEntry);
  115. }
  116. }
  117. if (dwErr != ERROR_SUCCESS) {
  118. goto Cleanup;
  119. }
  120. allValues[i] = NULL;
  121. rpValuesToFree[i] = NULL;
  122. //
  123. // Now we need to allocate the memory to hold this vector and return the results.
  124. //
  125. // First see how much space we need
  126. //
  127. for (i = len = cValues = 0; allValues[i]; i++) {
  128. len += sizeof(LPWSTR) + (wcslen(allValues[i]) + 1) * sizeof(WCHAR);
  129. cValues++;
  130. }
  131. len += sizeof(LPWSTR);
  132. dwErr = NetApiBufferAllocate(len, (PVOID *)&resultVector);
  133. if (dwErr != NO_ERROR)
  134. goto Cleanup;
  135. RtlZeroMemory(resultVector, len);
  136. pstr = (LPWSTR)((PCHAR)resultVector + (cValues + 1) * sizeof(LPWSTR));
  137. len -= (cValues+1) * sizeof(LPWSTR);
  138. for (i = cValues = 0; allValues[i] && len >= sizeof(WCHAR); i++) {
  139. resultVector[cValues] = pstr;
  140. wcscpy(pstr, allValues[i]);
  141. slen = wcslen(allValues[i]);
  142. pstr += slen + 1;
  143. len -= (slen + 1) * sizeof(WCHAR);
  144. cValues++;
  145. }
  146. *List = resultVector;
  147. Cleanup:
  148. if (rpValuesToFree != NULL) {
  149. for (i = 0; rpValuesToFree[i] != NULL; i++) {
  150. ldap_value_free(rpValuesToFree[i]);
  151. }
  152. }
  153. if (allValues != NULL) {
  154. NetApiBufferFree(allValues);
  155. }
  156. if (pMsg != NULL) {
  157. ldap_msgfree(pMsg);
  158. }
  159. if (dfsDn != NULL) {
  160. free(dfsDn);
  161. }
  162. if (pLDAP != NULL) {
  163. ldap_unbind(pLDAP);
  164. }
  165. if (fSwDebug)
  166. MyPrintf(L"NetDfsRootEnum exit %d\r\n", dwErr);
  167. return dwErr;
  168. }
  169. DWORD
  170. NetDfsRootServerEnum(
  171. LDAP *pldap,
  172. LPWSTR wszDfsConfigDN,
  173. LPWSTR **ppRootList)
  174. {
  175. DWORD dwErr = ERROR_SUCCESS;
  176. DWORD cServers;
  177. DWORD cRoots;
  178. DWORD i;
  179. LPWSTR *pRootList = NULL;
  180. ULONG Size;
  181. WCHAR *pWc;
  182. PLDAPMessage pMsg = NULL;
  183. LDAPMessage *pmsgServers;
  184. LPWSTR rgAttrs[5];
  185. PWCHAR *rgServers = NULL;
  186. if (fSwDebug)
  187. MyPrintf(L"DfspCreateRootServerList(%ws)\r\n",
  188. wszDfsConfigDN);
  189. //
  190. // Search for the FtDfs object
  191. //
  192. rgAttrs[0] = L"remoteServerName";
  193. rgAttrs[1] = NULL;
  194. dwErr = ldap_search_s(
  195. pldap,
  196. wszDfsConfigDN,
  197. LDAP_SCOPE_BASE,
  198. L"(objectClass=*)",
  199. rgAttrs,
  200. 0,
  201. &pMsg);
  202. if (dwErr != ERROR_SUCCESS) {
  203. dwErr = LdapMapErrorToWin32(dwErr);
  204. goto Cleanup;
  205. }
  206. pmsgServers = ldap_first_entry(pldap, pMsg);
  207. if (pmsgServers == NULL) {
  208. dwErr = ERROR_OUTOFMEMORY;
  209. goto Cleanup;
  210. }
  211. rgServers = ldap_get_values(
  212. pldap,
  213. pmsgServers,
  214. L"remoteServerName");
  215. if (rgServers == NULL) {
  216. dwErr = ERROR_OUTOFMEMORY;
  217. goto Cleanup;
  218. }
  219. cServers = ldap_count_values(rgServers);
  220. for (Size = cRoots = i = 0; i < cServers; i++) {
  221. // if (wcslen(rgServers[i]) < 3 || rgServers[i][0] != UNICODE_PATH_SEP)
  222. // continue;
  223. Size += (wcslen(rgServers[i]) + 1) * sizeof(WCHAR);
  224. cRoots++;
  225. }
  226. if (cRoots == 0) {
  227. *ppRootList = NULL;
  228. dwErr = ERROR_SUCCESS;
  229. goto Cleanup;
  230. }
  231. Size += sizeof(LPWSTR) * (cRoots + 1);
  232. pRootList = (LPWSTR *)malloc(Size);
  233. if (pRootList == NULL) {
  234. dwErr = ERROR_OUTOFMEMORY;
  235. goto Cleanup;
  236. }
  237. RtlZeroMemory(pRootList, Size);
  238. pWc = (WCHAR *)&pRootList[cRoots+1];
  239. for (cRoots = i = 0; i < cServers; i++) {
  240. pRootList[cRoots] = pWc;
  241. wcscpy(pWc, rgServers[i]);
  242. pWc += wcslen(rgServers[i]) + 1;
  243. cRoots++;
  244. }
  245. *ppRootList = pRootList;
  246. Cleanup:
  247. if (rgServers != NULL)
  248. ldap_value_free(rgServers);
  249. if (pMsg != NULL)
  250. ldap_msgfree( pMsg );
  251. if (fSwDebug) {
  252. if (dwErr == NO_ERROR && pRootList != NULL) {
  253. for (i = 0; pRootList[i] != NULL; i++)
  254. MyPrintf(L"[%d][%ws]\r\n", i, pRootList[i]);
  255. }
  256. MyPrintf(L"DfspCreateRootServerList returning %d\r\n", dwErr);
  257. }
  258. return( dwErr );
  259. }