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.

483 lines
12 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. //
  167. // Copy the DomainName into the structure
  168. //
  169. Status = RtlUpcaseUnicodeToOemN( DomainInfo->DomOemDomainName,
  170. sizeof(DomainInfo->DomOemDomainName),
  171. &DomainInfo->DomOemDomainNameLength,
  172. DomainName->Buffer,
  173. DomainName->Length );
  174. if (!NT_SUCCESS(Status)) {
  175. try_return( Status );
  176. }
  177. DomainInfo->DomOemDomainName[DomainInfo->DomOemDomainNameLength] = '\0';
  178. //
  179. // Build the domain name as a Netbios name
  180. // Trailing blank filled and <00> 16th byte
  181. //
  182. RtlCopyMemory( DomainInfo->DomNetbiosDomainName,
  183. DomainInfo->DomOemDomainName,
  184. DomainInfo->DomOemDomainNameLength );
  185. RtlFillMemory( DomainInfo->DomNetbiosDomainName+DomainInfo->DomOemDomainNameLength,
  186. NETBIOS_NAME_LEN-1-DomainInfo->DomOemDomainNameLength,
  187. ' ');
  188. DomainInfo->DomNetbiosDomainName[NETBIOS_NAME_LEN-1] = PRIMARY_DOMAIN_SIGNATURE;
  189. //
  190. // Copy the upcased Unicode domain name into the structure.
  191. //
  192. OemDomainName.Buffer = DomainInfo->DomOemDomainName;
  193. OemDomainName.Length = (USHORT)DomainInfo->DomOemDomainNameLength;
  194. OemDomainName.MaximumLength = OemDomainName.Length + sizeof(WCHAR);
  195. DomainInfo->DomUnicodeDomainName.Buffer = DomainInfo->DomUnicodeDomainNameBuffer;
  196. DomainInfo->DomUnicodeDomainName.MaximumLength = sizeof(DomainInfo->DomUnicodeDomainNameBuffer);
  197. Status = RtlOemStringToUnicodeString(&DomainInfo->DomUnicodeDomainName, &OemDomainName, FALSE);
  198. if (!NT_SUCCESS(Status)) {
  199. try_return( Status );
  200. }
  201. Status = STATUS_SUCCESS;
  202. try_exit:NOTHING;
  203. } finally {
  204. ExReleaseResourceLite(&BowserTransportDatabaseResource);
  205. }
  206. return Status;
  207. }
  208. PDOMAIN_INFO
  209. BowserFindDomain(
  210. PUNICODE_STRING DomainName OPTIONAL
  211. )
  212. /*++
  213. Routine Description:
  214. This routine will look up a domain given a name.
  215. Arguments:
  216. DomainName - The name of the domain to look up.
  217. Return Value:
  218. NULL - No such domain exists
  219. A pointer to the domain found. The found domain should be dereferenced
  220. using BowserDereferenceDomain.
  221. --*/
  222. {
  223. NTSTATUS Status;
  224. PLIST_ENTRY DomainEntry;
  225. PDOMAIN_INFO DomainInfo = NULL;
  226. CHAR OemDomainName[DNLEN+1];
  227. DWORD OemDomainNameLength;
  228. PAGED_CODE();
  229. ExAcquireResourceExclusiveLite(&BowserTransportDatabaseResource, TRUE);
  230. try {
  231. // If no domain was specified
  232. // try to return primary domain.
  233. //
  234. if ( DomainName == NULL || DomainName->Length == 0 ) {
  235. if ( !IsListEmpty( &BowserServicedDomains ) ) {
  236. DomainInfo = CONTAINING_RECORD(BowserServicedDomains.Flink, DOMAIN_INFO, Next);
  237. }
  238. //
  239. // If the domain name was specified,
  240. // Find it in the list of domains.
  241. //
  242. } else {
  243. //
  244. // Convert the domain name to OEM for faster comparison
  245. //
  246. Status = RtlUpcaseUnicodeToOemN( OemDomainName,
  247. DNLEN,
  248. &OemDomainNameLength,
  249. DomainName->Buffer,
  250. DomainName->Length );
  251. if ( NT_SUCCESS(Status)) {
  252. //
  253. // The PrimaryDomainInfo structure is allocated with no
  254. // domain name during bowser driver initialization.
  255. // Detect that case here and always return that domain
  256. // entry for all lookups.
  257. //
  258. if ( !IsListEmpty( &BowserServicedDomains ) ) {
  259. DomainInfo = CONTAINING_RECORD(BowserServicedDomains.Flink, DOMAIN_INFO, Next);
  260. if ( DomainInfo->DomOemDomainNameLength == 0 ) {
  261. try_return( DomainInfo );
  262. }
  263. }
  264. //
  265. // Loop trying to find this domain name.
  266. //
  267. for (DomainEntry = BowserServicedDomains.Flink ;
  268. DomainEntry != &BowserServicedDomains;
  269. DomainEntry = DomainEntry->Flink ) {
  270. DomainInfo = CONTAINING_RECORD(DomainEntry, DOMAIN_INFO, Next);
  271. if ( DomainInfo->DomOemDomainNameLength == OemDomainNameLength &&
  272. RtlCompareMemory( DomainInfo->DomOemDomainName,
  273. OemDomainName,
  274. OemDomainNameLength ) == OemDomainNameLength ) {
  275. try_return( DomainInfo );
  276. }
  277. }
  278. DomainInfo = NULL;
  279. }
  280. }
  281. try_exit:NOTHING;
  282. } finally {
  283. //
  284. // Reference the domain.
  285. //
  286. if ( DomainInfo != NULL ) {
  287. DomainInfo->ReferenceCount ++;
  288. dprintf(DPRT_REF, ("Reference domain %lx. Count now %lx\n", DomainInfo, DomainInfo->ReferenceCount));
  289. }
  290. ExReleaseResourceLite(&BowserTransportDatabaseResource);
  291. }
  292. return DomainInfo;
  293. }
  294. VOID
  295. BowserDereferenceDomain(
  296. IN PDOMAIN_INFO DomainInfo
  297. )
  298. /*++
  299. Routine Description:
  300. Decrement the reference count on a domain.
  301. If the reference count goes to 0, remove the domain.
  302. On entry, the global BowserTransportDatabaseResource may not be locked
  303. Arguments:
  304. DomainInfo - The domain to dereference
  305. Return Value:
  306. None
  307. --*/
  308. {
  309. NTSTATUS Status;
  310. ULONG ReferenceCount;
  311. PAGED_CODE();
  312. //
  313. // Decrement the reference count
  314. //
  315. ExAcquireResourceExclusiveLite(&BowserTransportDatabaseResource, TRUE);
  316. ReferenceCount = -- DomainInfo->ReferenceCount;
  317. if ( ReferenceCount == 0 ) {
  318. RemoveEntryList( &DomainInfo->Next );
  319. }
  320. ExReleaseResourceLite(&BowserTransportDatabaseResource);
  321. dprintf(DPRT_REF, ("Dereference domain %lx. Count now %lx\n", DomainInfo, DomainInfo->ReferenceCount));
  322. if ( ReferenceCount != 0 ) {
  323. return;
  324. }
  325. //
  326. // Free the Domain Info structure.
  327. //
  328. dlog(DPRT_DOMAIN, ("%s: BowserDereferenceDomain: domain deleted.\n",
  329. DomainInfo->DomOemDomainName ));
  330. FREE_POOL(DomainInfo );
  331. }