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.

491 lines
13 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. domain.c
  5. Abstract:
  6. Code to manage primary and emulated networks.
  7. Author:
  8. Cliff Van Dyke (CliffV) 23-Jan-1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. //
  14. // Module specific globals
  15. //
  16. // Serialized by BowserTransportDatabaseResource
  17. LIST_ENTRY BowserServicedDomains = {0};
  18. //
  19. // Local procedure forwards.
  20. //
  21. #ifdef ALLOC_PRAGMA
  22. #pragma alloc_text(INIT, BowserInitializeDomains)
  23. #pragma alloc_text(PAGE, BowserCreateDomain)
  24. #pragma alloc_text(PAGE, BowserSetDomainName)
  25. #pragma alloc_text(PAGE, BowserFindDomain)
  26. #pragma alloc_text(PAGE, BowserDereferenceDomain)
  27. #endif
  28. VOID
  29. BowserInitializeDomains(
  30. VOID
  31. )
  32. /*++
  33. Routine Description:
  34. Initialize domain.c.
  35. Arguments:
  36. None
  37. Return Value:
  38. None.
  39. --*/
  40. {
  41. PAGED_CODE();
  42. //
  43. // Initialize globals
  44. //
  45. InitializeListHead(&BowserServicedDomains);
  46. }
  47. PDOMAIN_INFO
  48. BowserCreateDomain(
  49. PUNICODE_STRING DomainName,
  50. PUNICODE_STRING ComputerName
  51. )
  52. /*++
  53. Routine Description:
  54. Find the existing domain definition or create a new domain to browse on.
  55. Arguments:
  56. DomainName - Name of the domain to browse on
  57. ComputerName - emulated computer name for this domain.
  58. Return Value:
  59. NULL - No such domain exists
  60. A pointer to the domain found/created. The found/created domain should be dereferenced
  61. using BowserDereferenceDomain.
  62. --*/
  63. {
  64. NTSTATUS Status;
  65. PDOMAIN_INFO DomainInfo = NULL;
  66. ULONG OemComputerNameLength;
  67. PAGED_CODE();
  68. dlog(DPRT_DOMAIN, ("%wZ: BowserCreateDomain\n", DomainName));
  69. try {
  70. ExAcquireResourceExclusiveLite(&BowserTransportDatabaseResource, TRUE);
  71. //
  72. // If the domain already exists, use it.
  73. //
  74. DomainInfo = BowserFindDomain( DomainName );
  75. if ( DomainInfo == NULL) {
  76. //
  77. // Allocate a structure describing the new domain.
  78. //
  79. DomainInfo = ALLOCATE_POOL(NonPagedPool, sizeof(DOMAIN_INFO), POOL_DOMAIN_INFO);
  80. if ( DomainInfo == NULL ) {
  81. try_return( Status = STATUS_NO_MEMORY );
  82. }
  83. RtlZeroMemory( DomainInfo, sizeof(DOMAIN_INFO) );
  84. //
  85. // Create an interim reference count for this domain.
  86. //
  87. // One for the caller.
  88. //
  89. // We don't increment the reference count for being in the global list since
  90. // the domain info structure is merely a performance enchancements that lives
  91. // only because it is referenced by a network.
  92. //
  93. DomainInfo->ReferenceCount = 1;
  94. //
  95. // Link the domain into the list of domains
  96. //
  97. // The primary domain is at the front of the list.
  98. //
  99. InsertTailList(&BowserServicedDomains, &DomainInfo->Next);
  100. }
  101. //
  102. // Copy the DomainName into the structure
  103. //
  104. Status = BowserSetDomainName( DomainInfo, DomainName );
  105. if (!NT_SUCCESS(Status)) {
  106. try_return( Status );
  107. }
  108. //
  109. // Copy the OEM Computer name into the structure.
  110. //
  111. if ( ComputerName->Length > CNLEN*sizeof(WCHAR) ) {
  112. try_return( Status = STATUS_INVALID_PARAMETER );
  113. }
  114. Status = RtlUpcaseUnicodeToOemN( DomainInfo->DomOemComputerNameBuffer,
  115. sizeof(DomainInfo->DomOemComputerNameBuffer)-1,
  116. &OemComputerNameLength,
  117. ComputerName->Buffer,
  118. ComputerName->Length );
  119. if (!NT_SUCCESS(Status)) {
  120. try_return( Status );
  121. }
  122. DomainInfo->DomOemComputerNameBuffer[OemComputerNameLength] = '\0';
  123. DomainInfo->DomOemComputerName.Buffer = DomainInfo->DomOemComputerNameBuffer;
  124. DomainInfo->DomOemComputerName.Length = (USHORT)OemComputerNameLength;
  125. DomainInfo->DomOemComputerName.MaximumLength = (USHORT)(OemComputerNameLength + 1);
  126. //
  127. // Copy the upcased Unicode Computer name into the structure.
  128. //
  129. DomainInfo->DomUnicodeComputerName.Buffer = DomainInfo->DomUnicodeComputerNameBuffer;
  130. DomainInfo->DomUnicodeComputerName.MaximumLength = sizeof(DomainInfo->DomUnicodeComputerNameBuffer);
  131. Status = RtlOemStringToUnicodeString(&DomainInfo->DomUnicodeComputerName, &DomainInfo->DomOemComputerName, FALSE);
  132. if (!NT_SUCCESS(Status)) {
  133. try_return( Status );
  134. }
  135. Status = STATUS_SUCCESS;
  136. try_exit:NOTHING;
  137. } finally {
  138. if ( !NT_SUCCESS(Status) && DomainInfo != NULL ) {
  139. BowserDereferenceDomain( DomainInfo );
  140. DomainInfo = NULL;
  141. }
  142. ExReleaseResourceLite(&BowserTransportDatabaseResource);
  143. }
  144. return DomainInfo;
  145. }
  146. NTSTATUS
  147. BowserSetDomainName(
  148. PDOMAIN_INFO DomainInfo,
  149. PUNICODE_STRING DomainName
  150. )
  151. /*++
  152. Routine Description:
  153. Find the existing domain definition or create a new domain to browse on.
  154. Arguments:
  155. DomainName - Name of the domain to browse on
  156. ComputerName - emulated computer name for this domain.
  157. Return Value:
  158. Status of the operation
  159. --*/
  160. {
  161. NTSTATUS Status;
  162. STRING OemDomainName;
  163. PAGED_CODE();
  164. try {
  165. ExAcquireResourceExclusiveLite(&BowserTransportDatabaseResource, TRUE);
  166. // if the alignment of the name given is bad, return error
  167. if ( !POINTER_IS_ALIGNED( DomainName->Buffer, ALIGN_WCHAR ) ) {
  168. try_return( STATUS_DATATYPE_MISALIGNMENT_ERROR );
  169. }
  170. //
  171. // Copy the DomainName into the structure
  172. //
  173. Status = RtlUpcaseUnicodeToOemN( DomainInfo->DomOemDomainName,
  174. sizeof(DomainInfo->DomOemDomainName),
  175. &DomainInfo->DomOemDomainNameLength,
  176. DomainName->Buffer,
  177. DomainName->Length );
  178. if (!NT_SUCCESS(Status)) {
  179. try_return( Status );
  180. }
  181. DomainInfo->DomOemDomainName[DomainInfo->DomOemDomainNameLength] = '\0';
  182. //
  183. // Build the domain name as a Netbios name
  184. // Trailing blank filled and <00> 16th byte
  185. //
  186. RtlCopyMemory( DomainInfo->DomNetbiosDomainName,
  187. DomainInfo->DomOemDomainName,
  188. DomainInfo->DomOemDomainNameLength );
  189. RtlFillMemory( DomainInfo->DomNetbiosDomainName+DomainInfo->DomOemDomainNameLength,
  190. NETBIOS_NAME_LEN-1-DomainInfo->DomOemDomainNameLength,
  191. ' ');
  192. DomainInfo->DomNetbiosDomainName[NETBIOS_NAME_LEN-1] = PRIMARY_DOMAIN_SIGNATURE;
  193. //
  194. // Copy the upcased Unicode domain name into the structure.
  195. //
  196. OemDomainName.Buffer = DomainInfo->DomOemDomainName;
  197. OemDomainName.Length = (USHORT)DomainInfo->DomOemDomainNameLength;
  198. OemDomainName.MaximumLength = OemDomainName.Length + sizeof(WCHAR);
  199. DomainInfo->DomUnicodeDomainName.Buffer = DomainInfo->DomUnicodeDomainNameBuffer;
  200. DomainInfo->DomUnicodeDomainName.MaximumLength = sizeof(DomainInfo->DomUnicodeDomainNameBuffer);
  201. Status = RtlOemStringToUnicodeString(&DomainInfo->DomUnicodeDomainName, &OemDomainName, FALSE);
  202. if (!NT_SUCCESS(Status)) {
  203. try_return( Status );
  204. }
  205. Status = STATUS_SUCCESS;
  206. try_exit:NOTHING;
  207. } finally {
  208. ExReleaseResourceLite(&BowserTransportDatabaseResource);
  209. }
  210. return Status;
  211. }
  212. PDOMAIN_INFO
  213. BowserFindDomain(
  214. PUNICODE_STRING DomainName OPTIONAL
  215. )
  216. /*++
  217. Routine Description:
  218. This routine will look up a domain given a name.
  219. Arguments:
  220. DomainName - The name of the domain to look up.
  221. Return Value:
  222. NULL - No such domain exists
  223. A pointer to the domain found. The found domain should be dereferenced
  224. using BowserDereferenceDomain.
  225. --*/
  226. {
  227. NTSTATUS Status;
  228. PLIST_ENTRY DomainEntry;
  229. PDOMAIN_INFO DomainInfo = NULL;
  230. CHAR OemDomainName[DNLEN+1];
  231. DWORD OemDomainNameLength;
  232. PAGED_CODE();
  233. ExAcquireResourceExclusiveLite(&BowserTransportDatabaseResource, TRUE);
  234. try {
  235. // If no domain was specified
  236. // try to return primary domain.
  237. //
  238. if ( DomainName == NULL || DomainName->Length == 0 ) {
  239. if ( !IsListEmpty( &BowserServicedDomains ) ) {
  240. DomainInfo = CONTAINING_RECORD(BowserServicedDomains.Flink, DOMAIN_INFO, Next);
  241. }
  242. // if the alignment of the name given is bad, return null
  243. } else if ( !POINTER_IS_ALIGNED( DomainName->Buffer, ALIGN_WCHAR ) ) {
  244. DomainInfo = NULL;
  245. //
  246. // If the domain name was specified,
  247. // Find it in the list of domains.
  248. //
  249. } else {
  250. //
  251. // Convert the domain name to OEM for faster comparison
  252. //
  253. Status = RtlUpcaseUnicodeToOemN( OemDomainName,
  254. DNLEN,
  255. &OemDomainNameLength,
  256. DomainName->Buffer,
  257. DomainName->Length );
  258. if ( NT_SUCCESS(Status)) {
  259. //
  260. // The PrimaryDomainInfo structure is allocated with no
  261. // domain name during bowser driver initialization.
  262. // Detect that case here and always return that domain
  263. // entry for all lookups.
  264. //
  265. if ( !IsListEmpty( &BowserServicedDomains ) ) {
  266. DomainInfo = CONTAINING_RECORD(BowserServicedDomains.Flink, DOMAIN_INFO, Next);
  267. if ( DomainInfo->DomOemDomainNameLength == 0 ) {
  268. try_return( DomainInfo );
  269. }
  270. }
  271. //
  272. // Loop trying to find this domain name.
  273. //
  274. for (DomainEntry = BowserServicedDomains.Flink ;
  275. DomainEntry != &BowserServicedDomains;
  276. DomainEntry = DomainEntry->Flink ) {
  277. DomainInfo = CONTAINING_RECORD(DomainEntry, DOMAIN_INFO, Next);
  278. if ( DomainInfo->DomOemDomainNameLength == OemDomainNameLength &&
  279. RtlCompareMemory( DomainInfo->DomOemDomainName,
  280. OemDomainName,
  281. OemDomainNameLength ) == OemDomainNameLength ) {
  282. try_return( DomainInfo );
  283. }
  284. }
  285. DomainInfo = NULL;
  286. }
  287. }
  288. try_exit:NOTHING;
  289. } finally {
  290. //
  291. // Reference the domain.
  292. //
  293. if ( DomainInfo != NULL ) {
  294. DomainInfo->ReferenceCount ++;
  295. dprintf(DPRT_REF, ("Reference domain %lx. Count now %lx\n", DomainInfo, DomainInfo->ReferenceCount));
  296. }
  297. ExReleaseResourceLite(&BowserTransportDatabaseResource);
  298. }
  299. return DomainInfo;
  300. }
  301. VOID
  302. BowserDereferenceDomain(
  303. IN PDOMAIN_INFO DomainInfo
  304. )
  305. /*++
  306. Routine Description:
  307. Decrement the reference count on a domain.
  308. If the reference count goes to 0, remove the domain.
  309. On entry, the global BowserTransportDatabaseResource may not be locked
  310. Arguments:
  311. DomainInfo - The domain to dereference
  312. Return Value:
  313. None
  314. --*/
  315. {
  316. NTSTATUS Status;
  317. ULONG ReferenceCount;
  318. PAGED_CODE();
  319. //
  320. // Decrement the reference count
  321. //
  322. ExAcquireResourceExclusiveLite(&BowserTransportDatabaseResource, TRUE);
  323. ReferenceCount = -- DomainInfo->ReferenceCount;
  324. if ( ReferenceCount == 0 ) {
  325. RemoveEntryList( &DomainInfo->Next );
  326. }
  327. ExReleaseResourceLite(&BowserTransportDatabaseResource);
  328. dprintf(DPRT_REF, ("Dereference domain %lx. Count now %lx\n", DomainInfo, DomainInfo->ReferenceCount));
  329. if ( ReferenceCount != 0 ) {
  330. return;
  331. }
  332. //
  333. // Free the Domain Info structure.
  334. //
  335. dlog(DPRT_DOMAIN, ("%s: BowserDereferenceDomain: domain deleted.\n",
  336. DomainInfo->DomOemDomainName ));
  337. FREE_POOL(DomainInfo );
  338. }