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.

585 lines
19 KiB

  1. //++
  2. //
  3. // Copyright (C) Microsoft Corporation, 1987 - 1999
  4. //
  5. // Module Name:
  6. //
  7. // member.c
  8. //
  9. // Abstract:
  10. //
  11. // Queries into network drivers
  12. //
  13. // Author:
  14. //
  15. // Anilth - 4-20-1998
  16. //
  17. // Environment:
  18. //
  19. // User mode only.
  20. // Contains NT-specific code.
  21. //
  22. // Revision History:
  23. //
  24. //--
  25. #include "precomp.h"
  26. #undef IsEqualGUID
  27. #include "objbase.h"
  28. #include "regutil.h"
  29. #include "strings.h"
  30. const WCHAR c_wszUserDnsDomain[] = L"USERDNSDOMAIN";
  31. BOOL IsSysVolReady(NETDIAG_PARAMS* pParams);
  32. /*!--------------------------------------------------------------------------
  33. MemberTest
  34. Determine the machines role and membership.
  35. Arguments:
  36. None.
  37. Return Value:
  38. TRUE: Test suceeded.
  39. FALSE: Test failed
  40. Author: KennT
  41. ---------------------------------------------------------------------------*/
  42. HRESULT MemberTest(NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults)
  43. {
  44. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pPrimaryDomain = NULL;
  45. DWORD dwErr;
  46. NTSTATUS Status;
  47. DWORD LogonServerLength;
  48. WCHAR swzLogonServer[MAX_PATH+1];
  49. int iBuildNo;
  50. BOOL fDomain; // TRUE if domain, FALSE is workgroup
  51. LSA_HANDLE PolicyHandle = NULL;
  52. PPOLICY_DNS_DOMAIN_INFO pPolicyDomainInfo = NULL;
  53. OBJECT_ATTRIBUTES ObjAttributes;
  54. PrintStatusMessage(pParams,0, IDS_MEMBER_STATUS_MSG);
  55. //
  56. // Get the build number of this machine
  57. //
  58. if (pResults->Global.pszCurrentBuildNumber &&
  59. (pResults->Global.pszCurrentBuildNumber[0] == 0))
  60. {
  61. PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
  62. PrintStatusMessage(pParams,0, IDS_MEMBER_CANNOT_DETERMINE_BUILD);
  63. pResults->Global.hrMemberTestResult = E_FAIL;
  64. return E_FAIL;
  65. }
  66. iBuildNo = _ttoi( pResults->Global.pszCurrentBuildNumber );
  67. // Assmume that the test has succeeded
  68. pResults->Global.hrMemberTestResult = hrOK;
  69. //
  70. // Get the name of the domain this machine is a member of
  71. //
  72. dwErr = DsRoleGetPrimaryDomainInformation(
  73. NULL, // local call
  74. DsRolePrimaryDomainInfoBasic,
  75. (PBYTE *) &pPrimaryDomain);
  76. pResults->Global.pPrimaryDomainInfo = pPrimaryDomain;
  77. if (dwErr != NO_ERROR)
  78. {
  79. PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
  80. PrintStatusMessage(pParams,0, IDS_MEMBER_CANNOT_DETERMINE_DOMAIN);
  81. pResults->Global.hrMemberTestResult = E_FAIL;
  82. goto Cleanup;
  83. }
  84. //
  85. // Handle being a member of a domain
  86. //
  87. if ( pPrimaryDomain->MachineRole != DsRole_RoleStandaloneWorkstation &&
  88. pPrimaryDomain->MachineRole != DsRole_RoleStandaloneServer )
  89. {
  90. //
  91. // Ensure the netlogon service is running.
  92. //
  93. dwErr = IsServiceStarted( _T("Netlogon") );
  94. if ( dwErr != NO_ERROR )
  95. {
  96. PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
  97. PrintStatusMessage(pParams,0, IDS_MEMBER_NETLOGON_NOT_RUNNING);
  98. }
  99. else
  100. {
  101. pResults->Global.fNetlogonIsRunning = TRUE;
  102. }
  103. //
  104. // Save the name of this domain as a domain to test.
  105. // Do NOT free this up. This will get freed up
  106. // by the code that frees up the list of domains.
  107. pResults->Global.pMemberDomain = AddTestedDomain( pParams,
  108. pResults,
  109. pPrimaryDomain->DomainNameFlat,
  110. pPrimaryDomain->DomainNameDns,
  111. TRUE );
  112. if (pResults->Global.pMemberDomain == NULL)
  113. {
  114. PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
  115. pResults->Global.hrMemberTestResult = S_FALSE;
  116. goto Cleanup;
  117. }
  118. //
  119. // Get the SID of the domain we're a member of
  120. //
  121. InitializeObjectAttributes(
  122. &ObjAttributes,
  123. NULL,
  124. 0L,
  125. NULL,
  126. NULL
  127. );
  128. Status = LsaOpenPolicy(
  129. NULL,
  130. &ObjAttributes,
  131. POLICY_VIEW_LOCAL_INFORMATION,
  132. &PolicyHandle );
  133. if (! NT_SUCCESS(Status))
  134. {
  135. PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
  136. PrintDebugSz(pParams, 0, _T(" [FATAL] Member: Cannot LsaOpenPolicy."));
  137. pResults->Global.hrMemberTestResult = S_FALSE;
  138. goto Cleanup;
  139. }
  140. Status = LsaQueryInformationPolicy(
  141. PolicyHandle,
  142. PolicyDnsDomainInformation,
  143. (PVOID *) &pPolicyDomainInfo
  144. );
  145. if (! NT_SUCCESS(Status))
  146. {
  147. PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
  148. if (pParams->fDebugVerbose)
  149. PrintDebugSz(pParams, 0, _T(" [FATAL] Member: Cannot LsaQueryInformationPolicy (PolicyDnsDomainInformation).") );
  150. pResults->Global.hrMemberTestResult = S_FALSE;
  151. goto Cleanup;
  152. }
  153. if ( pPolicyDomainInfo->Sid == NULL )
  154. {
  155. PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
  156. // IDS_MEMBER_11206 " [FATAL] Member: Cannot LsaQueryInformationPolicy has no domain sid."
  157. PrintDebug(pParams, 0, IDS_MEMBER_11206 );
  158. pResults->Global.hrMemberTestResult = S_FALSE;
  159. goto Cleanup;
  160. }
  161. //
  162. // Save the domain sid for other tests
  163. //
  164. pResults->Global.pMemberDomain->DomainSid =
  165. Malloc(RtlLengthSid(pPolicyDomainInfo->Sid));
  166. if (pResults->Global.pMemberDomain->DomainSid == NULL)
  167. {
  168. PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
  169. // IDS_MEMBER_11207 " Member: Out of memory\n"
  170. PrintDebug(pParams, 0, IDS_MEMBER_11207);
  171. pResults->Global.hrMemberTestResult = S_FALSE;
  172. goto Cleanup;
  173. }
  174. RtlCopyMemory( pResults->Global.pMemberDomain->DomainSid,
  175. pPolicyDomainInfo->Sid,
  176. RtlLengthSid( pPolicyDomainInfo->Sid ) );
  177. }
  178. //Bug 293635, check whether system volume is ready if the machine is a DC
  179. if (DsRole_RoleBackupDomainController == pPrimaryDomain->MachineRole ||
  180. DsRole_RolePrimaryDomainController == pPrimaryDomain->MachineRole)
  181. {
  182. pResults->Global.fSysVolNotReady = !IsSysVolReady(pParams);
  183. if (pResults->Global.fSysVolNotReady)
  184. pResults->Global.hrMemberTestResult = S_FALSE;
  185. }
  186. //
  187. // Get the name of the logged on user.
  188. //
  189. Status = LsaGetUserName( &pResults->Global.pLogonUser,
  190. &pResults->Global.pLogonDomainName );
  191. if ( !NT_SUCCESS(Status))
  192. {
  193. PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
  194. PrintStatusMessage(pParams,0, IDS_MEMBER_UNKNOWN_LOGON);
  195. pResults->Global.hrMemberTestResult = S_FALSE;
  196. goto Cleanup;
  197. }
  198. //
  199. // If we're not logged onto a local account,
  200. // add the logon domain to the list of tested domains
  201. //
  202. if ( _wcsicmp( pResults->Global.swzNetBiosName,
  203. pResults->Global.pLogonDomainName->Buffer ) != 0 )
  204. {
  205. LPWSTR pwszLogonDomainDnsName = NULL;
  206. DWORD cchLogonDomainDnsName = 0;
  207. cchLogonDomainDnsName = GetEnvironmentVariableW(c_wszUserDnsDomain,
  208. NULL,
  209. 0);
  210. if (cchLogonDomainDnsName)
  211. {
  212. pwszLogonDomainDnsName = Malloc(sizeof(WCHAR) * cchLogonDomainDnsName);
  213. ZeroMemory(pwszLogonDomainDnsName, sizeof(WCHAR) * cchLogonDomainDnsName);
  214. cchLogonDomainDnsName = GetEnvironmentVariableW(c_wszUserDnsDomain,
  215. pwszLogonDomainDnsName,
  216. cchLogonDomainDnsName);
  217. }
  218. // Save the name of this domain as a domain to test.
  219. // ------------------------------------------------------------
  220. if (cchLogonDomainDnsName && pwszLogonDomainDnsName && lstrlenW(pwszLogonDomainDnsName))
  221. {
  222. pResults->Global.pLogonDomain = AddTestedDomain( pParams, pResults,
  223. pResults->Global.pLogonDomainName->Buffer,
  224. pwszLogonDomainDnsName,
  225. FALSE );
  226. }
  227. else
  228. {
  229. pResults->Global.pLogonDomain = AddTestedDomain( pParams, pResults,
  230. pResults->Global.pLogonDomainName->Buffer,
  231. NULL,
  232. FALSE );
  233. }
  234. if (pwszLogonDomainDnsName)
  235. Free(pwszLogonDomainDnsName);
  236. if ( pResults->Global.pLogonDomain == NULL )
  237. {
  238. PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
  239. pResults->Global.hrMemberTestResult = S_FALSE;
  240. goto Cleanup;
  241. }
  242. }
  243. //
  244. // Get the name of the logon server.
  245. //
  246. LogonServerLength = GetEnvironmentVariableW(
  247. L"LOGONSERVER",
  248. swzLogonServer,
  249. DimensionOf(swzLogonServer));
  250. if ( LogonServerLength != 0 )
  251. {
  252. //
  253. // If the caller was supposed to logon to a domain,
  254. // and this isn't a DC,
  255. // see if the user logged on with cached credentials.
  256. //
  257. if ( pResults->Global.pLogonDomain != NULL &&
  258. pPrimaryDomain->MachineRole != DsRole_RoleBackupDomainController &&
  259. pPrimaryDomain->MachineRole != DsRole_RolePrimaryDomainController ) {
  260. LPWSTR pswzLogonServer;
  261. if ( swzLogonServer[0] == L'\\' && swzLogonServer[1] == L'\\')
  262. {
  263. pswzLogonServer = &swzLogonServer[2];
  264. }
  265. else
  266. {
  267. pswzLogonServer = &swzLogonServer[0];
  268. }
  269. pResults->Global.pswzLogonServer = _wcsdup(swzLogonServer);
  270. if ( _wcsicmp( pResults->Global.swzNetBiosName, pswzLogonServer ) == 0 )
  271. {
  272. pResults->Global.fLogonWithCachedCredentials = TRUE;
  273. }
  274. }
  275. }
  276. if (pPrimaryDomain->DomainNameFlat == NULL)
  277. {
  278. // the NetBIOS name is not specified
  279. if (FHrSucceeded(pResults->Global.hrMemberTestResult))
  280. pResults->Global.hrMemberTestResult = S_FALSE;
  281. }
  282. PrintStatusMessage(pParams,0, IDS_GLOBAL_PASS_NL);
  283. Cleanup:
  284. if ( pPolicyDomainInfo != NULL ) {
  285. (void) LsaFreeMemory((PVOID) pPolicyDomainInfo);
  286. }
  287. if ( PolicyHandle != NULL ) {
  288. (void) LsaClose(PolicyHandle);
  289. }
  290. return pResults->Global.hrMemberTestResult;
  291. }
  292. //Check if System Volume is ready
  293. //Author: NSun
  294. BOOL IsSysVolReady(NETDIAG_PARAMS* pParams)
  295. {
  296. DWORD dwData = 1;
  297. DWORD dwSize = sizeof(dwData);
  298. LONG lRet;
  299. BOOL fRetVal = TRUE;
  300. HKEY hkeyNetLogonParams = NULL;
  301. lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  302. c_szRegNetLogonParams,
  303. 0,
  304. KEY_READ,
  305. &hkeyNetLogonParams);
  306. if (ERROR_SUCCESS == lRet)
  307. {
  308. //it's ok that the SysVolReady value doesn't exist
  309. if (ReadRegistryDword(hkeyNetLogonParams,
  310. c_szRegSysVolReady,
  311. &dwData))
  312. {
  313. if (0 == dwData)
  314. fRetVal = FALSE;
  315. }
  316. RegCloseKey(hkeyNetLogonParams);
  317. }
  318. else
  319. PrintDebugSz(pParams, 0, _T("Failed to open the registry of NetLogon parameters.\n"));
  320. return fRetVal;
  321. }
  322. /*!--------------------------------------------------------------------------
  323. MemberGlobalPrint
  324. -
  325. Author: KennT
  326. ---------------------------------------------------------------------------*/
  327. void MemberGlobalPrint(IN NETDIAG_PARAMS *pParams,
  328. IN OUT NETDIAG_RESULT *pResults)
  329. {
  330. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pPrimaryDomain = NULL;
  331. BOOL fDomain = TRUE;
  332. TCHAR szName[256];
  333. int ids;
  334. if (pParams->fVerbose || !FHrOK(pResults->Global.hrMemberTestResult))
  335. {
  336. PrintNewLine(pParams, 2);
  337. PrintTestTitleResult(pParams, IDS_MEMBER_LONG, IDS_MEMBER_SHORT, TRUE,
  338. pResults->Global.hrMemberTestResult, 0);
  339. }
  340. pPrimaryDomain = pResults->Global.pPrimaryDomainInfo;
  341. if (!pPrimaryDomain)
  342. goto L_ERROR;
  343. //Bug 293635, check whether system volume is ready if the machine is a DC
  344. if (pResults->Global.fSysVolNotReady &&
  345. (DsRole_RoleBackupDomainController == pPrimaryDomain->MachineRole ||
  346. DsRole_RolePrimaryDomainController == pPrimaryDomain->MachineRole))
  347. {
  348. PrintMessage(pParams, IDS_MEMBER_SYSVOL_NOT_READY);
  349. }
  350. if (pParams->fReallyVerbose)
  351. //IDS_MEMBER_11208 " Machine is a: "
  352. PrintMessage(pParams, IDS_MEMBER_11208 );
  353. switch ( pPrimaryDomain->MachineRole )
  354. {
  355. case DsRole_RoleStandaloneWorkstation:
  356. // IDS_MEMBER_11209 "Standalone Workstation"
  357. ids = IDS_MEMBER_11209;
  358. fDomain = FALSE;
  359. break;
  360. case DsRole_RoleMemberWorkstation:
  361. // IDS_MEMBER_11210 "Member Workstation"
  362. ids = IDS_MEMBER_11210;
  363. fDomain = TRUE;
  364. break;
  365. case DsRole_RoleStandaloneServer:
  366. // IDS_MEMBER_11211 "Standalone Server"
  367. ids = IDS_MEMBER_11211;
  368. fDomain = FALSE;
  369. break;
  370. case DsRole_RoleMemberServer:
  371. // IDS_MEMBER_11212 "Member Server"
  372. ids = IDS_MEMBER_11212;
  373. fDomain = TRUE;
  374. break;
  375. case DsRole_RoleBackupDomainController:
  376. // IDS_MEMBER_11213 "Backup Domain Controller"
  377. ids = IDS_MEMBER_11213;
  378. fDomain = TRUE;
  379. break;
  380. case DsRole_RolePrimaryDomainController:
  381. // IDS_MEMBER_11214 "Primary Domain Controller"
  382. ids = IDS_MEMBER_11214;
  383. fDomain = TRUE;
  384. break;
  385. default:
  386. if (pParams->fReallyVerbose)
  387. {
  388. // IDS_MEMBER_11215 "<Unknown Role> %ld"
  389. PrintMessage(pParams, IDS_MEMBER_11215,
  390. pPrimaryDomain->MachineRole );
  391. }
  392. ids = 0;
  393. fDomain = TRUE;
  394. break;
  395. }
  396. if (pParams->fReallyVerbose && ids)
  397. PrintMessage(pParams, ids);
  398. if (pParams->fReallyVerbose)
  399. PrintNewLine(pParams, 1);
  400. if ( pPrimaryDomain->DomainNameFlat == NULL )
  401. {
  402. // IDS_MEMBER_11217 " Netbios Domain name is not specified: "
  403. // IDS_MEMBER_11232 " Netbios Workgroup name is not specified: "
  404. ids = fDomain ? IDS_MEMBER_11217 : IDS_MEMBER_11232;
  405. PrintMessage(pParams, ids);
  406. }
  407. else
  408. {
  409. // IDS_MEMBER_11216 " Netbios Domain name: %ws\n"
  410. // IDS_MEMBER_11218 " Netbios Workgroup name: %ws\n"
  411. ids = fDomain ? IDS_MEMBER_11216 : IDS_MEMBER_11218;
  412. if (pParams->fReallyVerbose)
  413. PrintMessage(pParams, ids,
  414. pPrimaryDomain->DomainNameFlat );
  415. }
  416. if ( pPrimaryDomain->DomainNameDns == NULL )
  417. {
  418. // IDS_MEMBER_11219 " Dns domain name is not specified.\n"
  419. PrintMessage(pParams, IDS_MEMBER_11219 );
  420. }
  421. else
  422. {
  423. if (pParams->fReallyVerbose)
  424. // IDS_MEMBER_11220 " Dns domain name: %ws\n"
  425. PrintMessage(pParams, IDS_MEMBER_11220,
  426. pPrimaryDomain->DomainNameDns );
  427. }
  428. if ( pPrimaryDomain->DomainForestName == NULL )
  429. {
  430. // IDS_MEMBER_11221 " Dns forest name is not specified.\n"
  431. PrintMessage(pParams, IDS_MEMBER_11221 );
  432. }
  433. else
  434. {
  435. if (pParams->fReallyVerbose)
  436. // IDS_MEMBER_11222 " Dns forest name: %ws\n"
  437. PrintMessage(pParams, IDS_MEMBER_11222,
  438. pPrimaryDomain->DomainForestName );
  439. }
  440. if ( pParams->fReallyVerbose )
  441. {
  442. WCHAR swzGuid[64];
  443. // IDS_MEMBER_11223 " Domain Guid: "
  444. PrintMessage(pParams, IDS_MEMBER_11223);
  445. StringFromGUID2(&pPrimaryDomain->DomainGuid,
  446. swzGuid,
  447. DimensionOf(swzGuid));
  448. PrintMessage(pParams, IDS_GLOBAL_WSTRING, swzGuid);
  449. PrintNewLine(pParams, 1);
  450. if ( pPrimaryDomain->MachineRole != DsRole_RoleStandaloneWorkstation &&
  451. pPrimaryDomain->MachineRole != DsRole_RoleStandaloneServer )
  452. {
  453. // IDS_MEMBER_11227 " Domain Sid: "
  454. PrintMessage(pParams, IDS_MEMBER_11227);
  455. PrintSid( pParams, pResults->Global.pMemberDomain->DomainSid );
  456. }
  457. // IDS_MEMBER_11228 " Logon User: %wZ\n"
  458. PrintMessage(pParams, IDS_MEMBER_11228, pResults->Global.pLogonUser );
  459. // IDS_MEMBER_11229 " Logon Domain: %wZ\n"
  460. PrintMessage(pParams, IDS_MEMBER_11229, pResults->Global.pLogonDomainName );
  461. }
  462. if ( pParams->fReallyVerbose)
  463. {
  464. if (pResults->Global.pswzLogonServer &&
  465. pResults->Global.pswzLogonServer[0])
  466. // IDS_MEMBER_11230 " Logon Server: %ws\n"
  467. PrintMessage(pParams, IDS_MEMBER_11230, pResults->Global.pswzLogonServer );
  468. if (pResults->Global.fLogonWithCachedCredentials)
  469. {
  470. // IDS_MEMBER_11231 " [WARNING] Member: User was logged on with cached credentials\n"
  471. PrintMessage(pParams, IDS_MEMBER_11231);
  472. }
  473. }
  474. L_ERROR:
  475. return;
  476. }
  477. /*!--------------------------------------------------------------------------
  478. MemberPerInterfacePrint
  479. -
  480. Author: KennT
  481. ---------------------------------------------------------------------------*/
  482. void MemberPerInterfacePrint(IN NETDIAG_PARAMS *pParams,
  483. IN NETDIAG_RESULT *pResults,
  484. IN INTERFACE_RESULT *pIfResult)
  485. {
  486. }
  487. /*!--------------------------------------------------------------------------
  488. MemberCleanup
  489. -
  490. Author: KennT
  491. ---------------------------------------------------------------------------*/
  492. void MemberCleanup(IN NETDIAG_PARAMS *pParams,
  493. IN OUT NETDIAG_RESULT *pResults)
  494. {
  495. free(pResults->Global.pswzLogonServer);
  496. pResults->Global.pswzLogonServer = NULL;
  497. }