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.

1495 lines
43 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: ncident.cpp
  7. //
  8. // Contents: Implementation of CNetCfgIdentification.
  9. //
  10. // Notes:
  11. //
  12. // History: 21 Mar 1997 danielwe Created
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include <nceh.h>
  18. #include "ncfgval.h"
  19. #include "ncident.h"
  20. #include "ncmisc.h"
  21. #include "ncreg.h"
  22. #include "nsbase.h"
  23. #include "nccom.h"
  24. #include "ncerror.h"
  25. //+---------------------------------------------------------------------------
  26. //
  27. // Function: DeleteStringAndSetNull
  28. //
  29. // Purpose: Frees the given string with delete, and sets it to
  30. // NULL before exiting.
  31. //
  32. // Arguments:
  33. // pszw [in, out] Pointer to string to be freed. The pointer is set to
  34. // NULL before the function exits.
  35. //
  36. // Returns: Nothing.
  37. //
  38. // Author: danielwe 1 Apr 1997
  39. //
  40. // Notes:
  41. //
  42. inline VOID DeleteStringAndSetNull(PWSTR *pszw)
  43. {
  44. AssertSz(pszw, "Param is NULL!");
  45. delete *pszw;
  46. *pszw = NULL;
  47. }
  48. inline HRESULT HrNetValidateName(IN PCWSTR lpMachine,
  49. IN PCWSTR lpName,
  50. IN PCWSTR lpAccount,
  51. IN PCWSTR lpPassword,
  52. IN NETSETUP_NAME_TYPE NameType)
  53. {
  54. NET_API_STATUS nerr;
  55. nerr = NetValidateName(const_cast<PWSTR>(lpMachine),
  56. const_cast<PWSTR>(lpName),
  57. const_cast<PWSTR>(lpAccount),
  58. const_cast<PWSTR>(lpPassword),
  59. NameType);
  60. TraceError("NetValidateName", HRESULT_FROM_WIN32(nerr));
  61. return HrFromNerr(nerr);
  62. }
  63. inline HRESULT HrNetJoinDomain(IN PWSTR lpMachine,
  64. IN PWSTR lpMachineObjectOU,
  65. IN PWSTR lpDomain,
  66. IN PWSTR lpAccount,
  67. IN PWSTR lpPassword,
  68. IN DWORD fJoinOptions)
  69. {
  70. NET_API_STATUS nerr;
  71. HRESULT hr;
  72. if ( fJoinOptions & NETSETUP_JOIN_DOMAIN )
  73. {
  74. hr = HrNetValidateName( lpMachine, lpDomain, lpAccount,
  75. lpPassword, NetSetupDomain );
  76. }
  77. else
  78. {
  79. hr = HrNetValidateName( lpMachine, lpDomain, lpAccount,
  80. lpPassword, NetSetupWorkgroup );
  81. }
  82. if (SUCCEEDED(hr))
  83. {
  84. nerr = NetJoinDomain(lpMachine, lpDomain, lpMachineObjectOU,
  85. lpAccount, lpPassword, fJoinOptions);
  86. TraceError("NetJoinDomain", HRESULT_FROM_WIN32(nerr));
  87. hr = HrFromNerr(nerr);
  88. }
  89. return hr;
  90. }
  91. inline HRESULT HrNetRenameInDomain(IN PWSTR lpMachine,
  92. IN PWSTR lpNewMachine,
  93. IN PWSTR lpAccount,
  94. IN PWSTR lpPassword,
  95. IN DWORD fJoinOptions)
  96. {
  97. NET_API_STATUS nerr;
  98. nerr = NetRenameMachineInDomain(lpMachine, lpNewMachine, lpAccount,
  99. lpPassword, fJoinOptions);
  100. TraceError("NetRenameMachineInDomain", HRESULT_FROM_WIN32(nerr));
  101. return HrFromNerr(nerr);
  102. }
  103. inline HRESULT HrNetUnjoinDomain(IN PWSTR lpAccount,
  104. IN PWSTR lpPassword,
  105. IN DWORD fJoinOptions)
  106. {
  107. NET_API_STATUS nerr;
  108. nerr = NetUnjoinDomain(NULL,lpAccount, lpPassword, fJoinOptions);
  109. TraceError("NetUnjoinDomain", HRESULT_FROM_WIN32(nerr));
  110. return HrFromNerr(nerr);
  111. }
  112. inline HRESULT HrNetGetJoinInformation(IN PWSTR lpNameBuffer,
  113. OUT LPDWORD lpNameBufferSize,
  114. OUT PNETSETUP_JOIN_STATUS BufferType)
  115. {
  116. NET_API_STATUS nerr;
  117. PWSTR JoinBuff = NULL;
  118. nerr = NetGetJoinInformation(NULL, &JoinBuff, BufferType);
  119. if ( nerr == NERR_Success ) {
  120. if ( *BufferType == NetSetupUnjoined ) {
  121. *lpNameBufferSize = 0;
  122. *lpNameBuffer = UNICODE_NULL;
  123. } else {
  124. if ( *lpNameBufferSize >= ( wcslen( JoinBuff ) +1 ) * sizeof( WCHAR ) ) {
  125. wcscpy( lpNameBuffer, JoinBuff );
  126. }
  127. *lpNameBufferSize = wcslen( JoinBuff ) +1;
  128. NetApiBufferFree( JoinBuff );
  129. }
  130. }
  131. TraceError("NetGetJoinInformation", HRESULT_FROM_WIN32(nerr));
  132. return HrFromNerr(nerr);
  133. }
  134. #ifdef DBG
  135. BOOL CNetCfgIdentification::FIsJoinedToDomain()
  136. {
  137. HRESULT hr = S_OK;
  138. NETSETUP_JOIN_STATUS js;
  139. WCHAR wszBuffer[256];
  140. DWORD cchBuffer = celems(wszBuffer);
  141. hr = HrNetGetJoinInformation(wszBuffer, &cchBuffer, &js);
  142. if (SUCCEEDED(hr))
  143. {
  144. if (js == NetSetupUnjoined)
  145. {
  146. // If we're as yet unjoined, only make sure that we marked our
  147. // internal state as being joined to a workgroup called "WORKGROUP"
  148. AssertSz(m_jsCur == NetSetupWorkgroupName, "We're unjoined but not "
  149. "joined to a workgroup!");
  150. AssertSz(m_szwCurDWName, "No current domain or "
  151. "workgroup name?");
  152. AssertSz(!lstrcmpiW(m_szwCurDWName,
  153. SzLoadIds(IDS_WORKGROUP)),
  154. "Workgroup name is not generic!");
  155. }
  156. else
  157. {
  158. AssertSz(js == m_jsCur, "Join status is not what we think it is!!");
  159. }
  160. }
  161. TraceError("CNetCfgIdentification::FIsJoinedToDomain - "
  162. "HrNetGetJoinInformation", hr);
  163. return (m_jsCur == NetSetupDomainName);
  164. }
  165. #endif
  166. //+---------------------------------------------------------------------------
  167. //
  168. // Function: HrFromNerr
  169. //
  170. // Purpose: Converts a NET_API_STATUS code into a NETCFG_E_* HRESULT
  171. // value.
  172. //
  173. // Arguments:
  174. // nerr [in] Status code to convert.
  175. //
  176. // Returns: HRESULT, Converted HRESULT value.
  177. //
  178. // Author: danielwe 21 Mar 1997
  179. //
  180. // Notes:
  181. //
  182. HRESULT HrFromNerr(NET_API_STATUS nerr)
  183. {
  184. HRESULT hr;
  185. switch (nerr)
  186. {
  187. case NERR_Success:
  188. hr = S_OK;
  189. break;
  190. case NERR_SetupAlreadyJoined:
  191. hr = NETCFG_E_ALREADY_JOINED;
  192. break;
  193. case ERROR_DUP_NAME:
  194. hr = NETCFG_E_NAME_IN_USE;
  195. break;
  196. case NERR_SetupNotJoined:
  197. hr = NETCFG_E_NOT_JOINED;
  198. break;
  199. // case NERR_SetupIsDC:
  200. // hr = NETCFG_E_MACHINE_IS_DC;
  201. // break;
  202. // case NERR_SetupNotAServer:
  203. // hr = NETCFG_E_NOT_A_SERVER;
  204. // break;
  205. // case NERR_SetupImproperRole:
  206. // hr = NETCFG_E_INVALID_ROLE;
  207. // break;
  208. case ERROR_INVALID_PARAMETER:
  209. hr = E_INVALIDARG;
  210. break;
  211. case ERROR_ACCESS_DENIED:
  212. hr = E_ACCESSDENIED;
  213. break;
  214. case NERR_InvalidComputer:
  215. case ERROR_NO_SUCH_DOMAIN:
  216. hr = NETCFG_E_INVALID_DOMAIN;
  217. break;
  218. default:
  219. // Generic INetCfgIdentification error
  220. //$ REVIEW (danielwe) 24 Jun 1997: What if this isn't a Win32 error?
  221. hr = HRESULT_FROM_WIN32(nerr);
  222. break;
  223. }
  224. return hr;
  225. }
  226. //
  227. // INetCfgIdentification implementation
  228. //
  229. //+---------------------------------------------------------------------------
  230. //
  231. // Member: CNetCfgIdentification::HrEnsureCurrentComputerName
  232. //
  233. // Purpose: Ensures that the current computer name exists to act on.
  234. //
  235. // Arguments:
  236. // (none)
  237. //
  238. // Returns: HRESULT, Error code.
  239. //
  240. // Author: danielwe 21 Mar 1997
  241. //
  242. // Notes: Sets the m_szwCurComputerName variable.
  243. //
  244. HRESULT CNetCfgIdentification::HrEnsureCurrentComputerName()
  245. {
  246. HRESULT hr = S_OK;
  247. if (!m_szwCurComputerName)
  248. {
  249. PWSTR pszwComputer;
  250. // Go get the current computer name because we don't know it yet.
  251. hr = HrGetCurrentComputerName(&pszwComputer);
  252. if (SUCCEEDED(hr))
  253. {
  254. // m_szwCurComputerName is now set as a side effect
  255. CoTaskMemFree(pszwComputer);
  256. }
  257. }
  258. AssertSz(FImplies(SUCCEEDED(hr), m_szwCurComputerName),
  259. "I MUST have a name here!");
  260. TraceError("CNetCfgIdentification::HrEnsureCurrentComputerName", hr);
  261. return hr;
  262. }
  263. //+---------------------------------------------------------------------------
  264. //
  265. // Member: CNetCfgIdentification::HrGetNewestComputerName
  266. //
  267. // Purpose: Places the most recently referenced computer name into the
  268. // output parameter.
  269. //
  270. // Arguments:
  271. // pwszName [out] Most recently referenced computer name.
  272. //
  273. // Returns: Possible Win32 error code.
  274. //
  275. // Author: danielwe 24 Mar 1997
  276. //
  277. // Notes: If the SetComputerName() method was never called, this sets
  278. // the m_szwCurComputerName variable and returns a pointer to it.
  279. // Otherwise, it will return a pointer to the computer name
  280. // given in the SetComputerName() call.
  281. //
  282. HRESULT CNetCfgIdentification::HrGetNewestComputerName(PCWSTR *pwszName)
  283. {
  284. HRESULT hr = S_OK;
  285. AssertSz(pwszName, "NULL out param!");
  286. *pwszName = NULL;
  287. // New computer name is absent, use current computer name.
  288. hr = HrEnsureCurrentComputerName();
  289. if (FAILED(hr))
  290. goto err;
  291. *pwszName = m_szwCurComputerName;
  292. err:
  293. TraceError("CNetCfgIdentification::HrGetNewestComputerName", hr);
  294. return hr;
  295. }
  296. //+---------------------------------------------------------------------------
  297. //
  298. // Member: CNetCfgIdentification::HrValidateMachineName
  299. //
  300. // Purpose: Validates the given machine name.
  301. //
  302. // Arguments:
  303. // szwName [in] Machine name to validate.
  304. //
  305. // Returns: S_OK if machine name is valid, NETCFG_E_NAME_IN_USE if machine
  306. // name is in use.
  307. //
  308. // Author: danielwe 24 Mar 1997
  309. //
  310. // Notes:
  311. //
  312. HRESULT CNetCfgIdentification::HrValidateMachineName(PCWSTR szwName)
  313. {
  314. HRESULT hr = S_OK;
  315. // Only validate if networking is installed
  316. hr = HrIsNetworkingInstalled();
  317. if (hr == S_OK)
  318. {
  319. // Current computer name is unused for validation of machine name.
  320. hr = HrNetValidateName(NULL,
  321. szwName,
  322. NULL, NULL,
  323. NetSetupMachine);
  324. if (FAILED(hr))
  325. {
  326. //$REVIEW(danielwe): What error code to return here?
  327. TraceError("NetValidateName - Machine Name", hr);
  328. }
  329. }
  330. else if (hr == S_FALSE)
  331. {
  332. // no networking installed. We're fine.
  333. hr = S_OK;
  334. }
  335. TraceError("CNetCfgIdentification::HrValidateMachineName", hr);
  336. return hr;
  337. }
  338. //+---------------------------------------------------------------------------
  339. //
  340. // Member: CNetCfgIdentification::HrValidateWorkgroupName
  341. //
  342. // Purpose: Validates the given workgroup name.
  343. //
  344. // Arguments:
  345. // szwName [in] Workgroup name to validate.
  346. //
  347. // Returns: S_OK if machine name is valid, NETCFG_E_NAME_IN_USE if machine
  348. // name is in use.
  349. //
  350. // Author: danielwe 24 Mar 1997
  351. //
  352. // Notes:
  353. //
  354. HRESULT CNetCfgIdentification::HrValidateWorkgroupName(PCWSTR szwName)
  355. {
  356. HRESULT hr = S_OK;
  357. PCWSTR wszComputerName = NULL;
  358. // If the user has changed the computer name, use it, otherwise get the
  359. // current computer name and use that.
  360. hr = HrGetNewestComputerName(&wszComputerName);
  361. if (FAILED(hr))
  362. goto err;
  363. AssertSz(wszComputerName, "We don't have a computer name!");
  364. hr = HrNetValidateName(const_cast<PWSTR>(wszComputerName),
  365. szwName, NULL, NULL, NetSetupWorkgroup);
  366. if (FAILED(hr))
  367. {
  368. //$REVIEW(danielwe): What error code to return here?
  369. TraceError("NetValidateName - Workgroup Name", hr);
  370. goto err;
  371. }
  372. err:
  373. TraceError("CNetCfgIdentification::HrValidateWorkgroupName", hr);
  374. return hr;
  375. }
  376. //+---------------------------------------------------------------------------
  377. //
  378. // Member: CNetCfgIdentification::HrValidateDomainName
  379. //
  380. // Purpose: Validates the given domain name.
  381. //
  382. // Arguments:
  383. // szwName [in] Name of domain to validate.
  384. // szwUserName [in] Username for authorization purposes.
  385. // szwPassword [in] Password for authorization purposes.
  386. //
  387. // Returns: S_OK if machine name is valid, NETCFG_E_INVALID_DOMAIN if
  388. // domain name is invalid (or non-existent).
  389. //
  390. // Author: danielwe 24 Mar 1997
  391. //
  392. // Notes:
  393. //
  394. HRESULT CNetCfgIdentification::HrValidateDomainName(PCWSTR szwName,
  395. PCWSTR szwUserName,
  396. PCWSTR szwPassword)
  397. {
  398. HRESULT hr = S_OK;
  399. // NetValidateName does not use the machine name in validating the
  400. // domain name. So it is NULL here.
  401. hr = HrNetValidateName(NULL, szwName,
  402. szwUserName,
  403. szwPassword,
  404. NetSetupDomain);
  405. if (FAILED(hr))
  406. {
  407. //$REVIEW(danielwe): What error code to return here?
  408. TraceError("NetValidateName - Domain Name", hr);
  409. goto err;
  410. }
  411. err:
  412. TraceError("CNetCfgIdentification::HrValidateDomainName", hr);
  413. return hr;
  414. }
  415. //+---------------------------------------------------------------------------
  416. //
  417. // Member: CNetCfgIdentification::Validate
  418. //
  419. // Purpose: Implements COM function to validate current set of values
  420. // used during the lifetime of this object.
  421. //
  422. // Arguments:
  423. // (none)
  424. //
  425. // Returns: HRESULT, Error code.
  426. //
  427. // Author: danielwe 21 Mar 1997
  428. //
  429. // Notes:
  430. //
  431. STDMETHODIMP CNetCfgIdentification::Validate()
  432. {
  433. HRESULT hr = S_OK;
  434. Validate_INetCfgIdentification_Validate();
  435. COM_PROTECT_TRY
  436. {
  437. if (m_szwNewDWName)
  438. {
  439. if (GetNewJoinStatus() == NetSetupWorkgroupName)
  440. {
  441. // Validate workgroup name
  442. hr = HrValidateWorkgroupName(m_szwNewDWName);
  443. if (FAILED(hr))
  444. goto err;
  445. }
  446. else if (GetNewJoinStatus() == NetSetupDomainName)
  447. {
  448. // Validate domain name
  449. hr = HrValidateDomainName(m_szwNewDWName, m_szwUserName,
  450. m_szwPassword);
  451. if (FAILED(hr))
  452. goto err;
  453. }
  454. #ifdef DBG
  455. else
  456. {
  457. AssertSz(FALSE, "Invalid join status!");
  458. }
  459. #endif
  460. }
  461. }
  462. COM_PROTECT_CATCH;
  463. err:
  464. // Translate all errors to S_FALSE.
  465. if (SUCCEEDED(hr))
  466. {
  467. m_fValid = TRUE;
  468. }
  469. else
  470. {
  471. // spew out trace *before* the assignment so we know what the *real*
  472. // error code was.
  473. TraceError("CNetCfgIdentification::Validate (before S_FALSE)", hr);
  474. hr = S_FALSE;
  475. }
  476. return hr;
  477. }
  478. //+---------------------------------------------------------------------------
  479. //
  480. // Member: CNetCfgIdentification::Cancel
  481. //
  482. // Purpose: Cancels any changes made during the lifetime of the object.
  483. //
  484. // Arguments:
  485. // (none)
  486. //
  487. // Returns:
  488. //
  489. // Author: danielwe 25 Mar 1997
  490. //
  491. // Notes: Resets state information and frees any memory previously
  492. // allocted.
  493. //
  494. STDMETHODIMP CNetCfgIdentification::Cancel()
  495. {
  496. HRESULT hr = S_OK;
  497. Validate_INetCfgIdentification_Cancel();
  498. COM_PROTECT_TRY
  499. {
  500. DeleteStringAndSetNull(&m_szwNewDWName);
  501. DeleteStringAndSetNull(&m_szwPassword);
  502. DeleteStringAndSetNull(&m_szwUserName);
  503. DeleteStringAndSetNull(&m_szwCurComputerName);
  504. DeleteStringAndSetNull(&m_szwCurDWName);
  505. m_dwJoinFlags = 0;
  506. m_dwCreateFlags = 0;
  507. m_fValid = FALSE;
  508. m_jsNew = NetSetupUnjoined;
  509. }
  510. COM_PROTECT_CATCH;
  511. return hr;
  512. }
  513. //+---------------------------------------------------------------------------
  514. //
  515. // Member: CNetCfgIdentification::Apply
  516. //
  517. // Purpose: Implements COM function to apply changes that were made
  518. // during the lifetime of this object.
  519. //
  520. // Arguments:
  521. // (none)
  522. //
  523. // Returns: HRESULT, Error code.
  524. //
  525. // Author: danielwe 21 Mar 1997
  526. //
  527. // Notes:
  528. //
  529. STDMETHODIMP CNetCfgIdentification::Apply()
  530. {
  531. HRESULT hr = S_OK;
  532. Validate_INetCfgIdentification_Apply();
  533. COM_PROTECT_TRY
  534. {
  535. // Has data been validated?
  536. if (!m_fValid)
  537. {
  538. hr = E_UNEXPECTED;
  539. goto err;
  540. }
  541. if (m_szwNewDWName)
  542. {
  543. if (GetNewJoinStatus() == NetSetupWorkgroupName)
  544. {
  545. // The user specified a workgroup name. This means they want
  546. // to join a workgroup.
  547. hr = HrJoinWorkgroup();
  548. if (FAILED(hr))
  549. goto err;
  550. }
  551. else if (GetNewJoinStatus() == NetSetupDomainName)
  552. {
  553. // The user specified a domain name. This means they want to
  554. // join a domain.
  555. hr = HrJoinDomain();
  556. if (FAILED(hr))
  557. goto err;
  558. }
  559. #ifdef DBG
  560. else
  561. {
  562. AssertSz(FALSE, "Invalid join status!");
  563. }
  564. #endif
  565. }
  566. }
  567. COM_PROTECT_CATCH;
  568. err:
  569. // Regardless of result, set valid flag to false again to require
  570. // Validate() to be called again before calling Apply().
  571. // $REVIEW (danielwe): Is this how we want to do it?
  572. m_fValid = FALSE;
  573. TraceError("CNetCfgIdentification::Apply", hr);
  574. return hr;
  575. }
  576. //+---------------------------------------------------------------------------
  577. //
  578. // Member: CNetCfgIdentification::HrGetCurrentComputerName
  579. //
  580. // Purpose: Calls the Win32 GetComputerName API to get the current
  581. // computer name.
  582. //
  583. // Arguments:
  584. // ppszwComputer [out] Returned computer name.
  585. //
  586. // Returns: HRESULT, Error code.
  587. //
  588. // Author: danielwe 21 Mar 1997
  589. //
  590. // Notes: Makes a private copy of the computer name if obtained from the
  591. // system (for further use).
  592. //
  593. HRESULT CNetCfgIdentification::HrGetCurrentComputerName(PWSTR* ppszwComputer)
  594. {
  595. HRESULT hr = S_OK;
  596. WCHAR szBuffer[MAX_COMPUTERNAME_LENGTH + 1];
  597. DWORD cchBuffer = celems(szBuffer);
  598. if (::GetComputerName(szBuffer, &cchBuffer))
  599. {
  600. // Make a copy for the out param.
  601. hr = HrCoTaskMemAllocAndDupSz (
  602. szBuffer, ppszwComputer);
  603. if (SUCCEEDED(hr))
  604. {
  605. // Make another copy for our own use.
  606. DeleteStringAndSetNull(&m_szwCurComputerName);
  607. m_szwCurComputerName = SzDupSz(szBuffer);
  608. AssertSz((DWORD)lstrlenW(*ppszwComputer) == cchBuffer,
  609. "This is not how big the string is!");
  610. }
  611. }
  612. else
  613. {
  614. TraceLastWin32Error("::GetComputerName");
  615. hr = HrFromLastWin32Error();
  616. }
  617. TraceError("CNetCfgIdentification::HrGetCurrentComputerName", hr);
  618. return hr;
  619. }
  620. static const WCHAR c_szRegKeyComputerName[] = L"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName";
  621. static const WCHAR c_szRegValueComputerName[] = L"ComputerName";
  622. //+---------------------------------------------------------------------------
  623. //
  624. // Member: CNetCfgIdentification::HrGetNewComputerName
  625. //
  626. // Purpose: Helper function to retreive the new computer name from the
  627. // registry. This will be the same as the active computer name
  628. // unless the user has changed the computer name since booting.
  629. //
  630. // Arguments:
  631. // ppszwComputer [out] Returns new computer name.
  632. //
  633. // Returns: S_OK if successful, Win32 error code otherwise.
  634. //
  635. // Author: danielwe 21 May 1997
  636. //
  637. // Notes:
  638. //
  639. HRESULT CNetCfgIdentification::HrGetNewComputerName(PWSTR* ppszwComputer)
  640. {
  641. HRESULT hr = S_OK;
  642. WCHAR szBuffer[MAX_COMPUTERNAME_LENGTH + 1];
  643. DWORD cbBuffer = sizeof(szBuffer);
  644. HKEY hkeyComputerName;
  645. hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyComputerName,
  646. KEY_READ, &hkeyComputerName);
  647. if (SUCCEEDED(hr))
  648. {
  649. hr = HrRegQuerySzBuffer(hkeyComputerName, c_szRegValueComputerName,
  650. szBuffer, &cbBuffer);
  651. if (SUCCEEDED(hr))
  652. {
  653. // Make a copy for the out param.
  654. hr = HrCoTaskMemAllocAndDupSz (
  655. szBuffer, ppszwComputer);
  656. AssertSz(FImplies(SUCCEEDED(hr),
  657. (lstrlenW(*ppszwComputer) + 1) * sizeof(WCHAR) == cbBuffer),
  658. "This is not how big the string is!");
  659. }
  660. RegCloseKey(hkeyComputerName);
  661. }
  662. TraceError("CNetCfgIdentification::HrGetCurrentComputerName", hr);
  663. return hr;
  664. }
  665. //+---------------------------------------------------------------------------
  666. //
  667. // Member: CNetCfgIdentification::HrEnsureCurrentDomainOrWorkgroupName
  668. //
  669. // Purpose: Obtains the current domain or workgroup to which this machine
  670. // belongs.
  671. //
  672. // Arguments:
  673. // (none)
  674. //
  675. // Returns: S_OK if success, error code otherwise.
  676. //
  677. // Author: danielwe 26 Mar 1997
  678. //
  679. // Notes: A machine can be joined to either or workgroup or a domain. It
  680. // must be joined to one or the other. If it is not, we'll use a
  681. // more or less hardcoded string and "fake it" as if the machine
  682. // was joined to a workgroup. The member variables:
  683. // m_jsCur and m_szwCurDWName are set by this function.
  684. //
  685. // This call only does work once. Subsequent calls do nothing.
  686. //
  687. HRESULT CNetCfgIdentification::HrEnsureCurrentDomainOrWorkgroupName()
  688. {
  689. HRESULT hr = S_OK;
  690. if (!m_szwCurDWName)
  691. {
  692. NETSETUP_JOIN_STATUS js;
  693. WCHAR wszBuffer[256];
  694. PCWSTR wszName;
  695. DWORD cchBuffer = celems(wszBuffer);
  696. hr = HrNetGetJoinInformation(wszBuffer, &cchBuffer, &js);
  697. if (FAILED(hr))
  698. goto err;
  699. AssertSz(FIff(*wszBuffer, cchBuffer), "Buffer size inconsistency!");
  700. if (js == NetSetupUnjoined)
  701. {
  702. // Uh oh. Machine is not joined to workgroup OR domain. Set
  703. // default workgroup name and proceed as if joined to a workgroup.
  704. js = NetSetupWorkgroupName;
  705. // Use default name since HrNetGetJoinInformation() will return
  706. // an empty string which is useless.
  707. wszName = SzLoadIds(IDS_WORKGROUP);
  708. }
  709. else
  710. {
  711. // Use string returned from HrNetGetJoinInformation().
  712. wszName = wszBuffer;
  713. }
  714. m_szwCurDWName = SzDupSz(wszName);
  715. m_jsCur = js;
  716. AssertSz(GetCurrentJoinStatus() == NetSetupWorkgroupName ||
  717. GetCurrentJoinStatus() == NetSetupDomainName,
  718. "Invalid join status flag!");
  719. }
  720. err:
  721. TraceError("CNetCfgIdentification::HrEnsureCurrentDomainOrWorkgroupName",
  722. hr);
  723. return hr;
  724. }
  725. //+---------------------------------------------------------------------------
  726. //
  727. // Member: CNetCfgIdentification::HrGetNewestDomainOrWorkgroupName
  728. //
  729. // Purpose: Returns the domain or workgroup name that was most recently
  730. // referenced.
  731. //
  732. // Arguments:
  733. // js [in] Tells whether the domain or workgroup name is wanted.
  734. // pwszName [out] Domain or workgroup name.
  735. //
  736. // Returns: S_OK if success, E_OUTOFMEMORY if no memory.
  737. //
  738. // Author: danielwe 26 Mar 1997
  739. //
  740. // Notes: If the requested name has not been set by the user in a prior
  741. // call, the current name is returned. Otherwise the name the
  742. // user chose previously is returned.
  743. //
  744. HRESULT CNetCfgIdentification::HrGetNewestDomainOrWorkgroupName(
  745. NETSETUP_JOIN_STATUS js,
  746. PCWSTR *pwszName)
  747. {
  748. HRESULT hr = S_OK;
  749. PWSTR szwOut = NULL;
  750. Assert(pwszName);
  751. if (m_szwNewDWName && (GetNewJoinStatus() == js))
  752. {
  753. // Give them back a copy of the domain or workgroup name they
  754. // previously gave us.
  755. szwOut = m_szwNewDWName;
  756. }
  757. else
  758. {
  759. // Get the current workgroup or domain for this machine. It has
  760. // to be in one or the other.
  761. hr = HrEnsureCurrentDomainOrWorkgroupName();
  762. if (FAILED(hr))
  763. goto err;
  764. if (GetCurrentJoinStatus() == js)
  765. {
  766. // Use the current name.
  767. szwOut = m_szwCurDWName;
  768. }
  769. }
  770. Assert(SUCCEEDED(hr));
  771. *pwszName = szwOut;
  772. err:
  773. TraceError("CNetCfgIdentification::HrGetNewestDomainOrWorkgroupName", hr);
  774. return hr;
  775. }
  776. //+---------------------------------------------------------------------------
  777. //
  778. // Member: CNetCfgIdentification::GetWorkgroupName
  779. //
  780. // Purpose: Implements COM function to get the current workgroup name.
  781. //
  782. // Arguments:
  783. // ppszwWorkgroup [out] Returns name of current workgroup.
  784. //
  785. // Returns: S_OK if succeeded, S_FALSE if machine is not joined to a
  786. // workgroup, error code otherwise.
  787. //
  788. // Author: danielwe 21 Mar 1997
  789. //
  790. // Notes:
  791. //
  792. STDMETHODIMP CNetCfgIdentification::GetWorkgroupName(PWSTR* ppszwWorkgroup)
  793. {
  794. HRESULT hr = S_OK;
  795. PCWSTR szwWorkgroup = NULL;
  796. Validate_INetCfgIdentification_GetWorkgroupName(ppszwWorkgroup);
  797. COM_PROTECT_TRY
  798. {
  799. *ppszwWorkgroup = NULL;
  800. hr = HrGetNewestDomainOrWorkgroupName(NetSetupWorkgroupName,
  801. &szwWorkgroup);
  802. if (FAILED(hr))
  803. goto err;
  804. if (szwWorkgroup)
  805. {
  806. hr = HrCoTaskMemAllocAndDupSz (
  807. szwWorkgroup, ppszwWorkgroup);
  808. AssertSz(FImplies(SUCCEEDED(hr), lstrlenW(*ppszwWorkgroup) > 0),
  809. "Why is *ppszwWorkgroup empty?");
  810. }
  811. else
  812. {
  813. // Not joined to a workgroup
  814. hr = S_FALSE;
  815. }
  816. }
  817. COM_PROTECT_CATCH;
  818. err:
  819. TraceError("CNetCfgIdentification::GetWorkgroupName",
  820. (hr == S_FALSE) ? S_OK : hr);
  821. return hr;
  822. }
  823. //+---------------------------------------------------------------------------
  824. //
  825. // Member: CNetCfgIdentification::GetDomainName
  826. //
  827. // Purpose: Implements COM function to get the current domain name.
  828. //
  829. // Arguments:
  830. // ppszwDomain [out] Returns name of domain to which this computer
  831. // currently belongs.
  832. //
  833. // Returns: S_OK if succeeded, S_FALSE if machine is not joined to a
  834. // domain, error code otherwise.
  835. //
  836. // Author: danielwe 21 Mar 1997
  837. //
  838. // Notes:
  839. //
  840. STDMETHODIMP CNetCfgIdentification::GetDomainName(PWSTR* ppszwDomain)
  841. {
  842. HRESULT hr = S_OK;
  843. PCWSTR szwDomain = NULL;
  844. Validate_INetCfgIdentification_GetDomainName(ppszwDomain);
  845. COM_PROTECT_TRY
  846. {
  847. *ppszwDomain = NULL;
  848. hr = HrGetNewestDomainOrWorkgroupName(NetSetupDomainName,
  849. &szwDomain);
  850. if (FAILED(hr))
  851. goto err;
  852. if (szwDomain)
  853. {
  854. hr = HrCoTaskMemAllocAndDupSz (
  855. szwDomain, ppszwDomain);
  856. AssertSz(FImplies(SUCCEEDED(hr), lstrlenW(*ppszwDomain) > 0),
  857. "Why is *ppszwDomain empty?");
  858. }
  859. else
  860. {
  861. // Not joined to a domain
  862. hr = S_FALSE;
  863. }
  864. }
  865. COM_PROTECT_CATCH;
  866. err:
  867. TraceError("CNetCfgIdentification::GetDomainName",
  868. (hr == S_FALSE) ? S_OK : hr);
  869. return hr;
  870. }
  871. //+---------------------------------------------------------------------------
  872. //
  873. // Member: CNetCfgIdentification::HrJoinWorkgroup
  874. //
  875. // Purpose: Actually performs the JoinWorkgroup function.
  876. //
  877. // Arguments:
  878. // (none)
  879. //
  880. // Returns: HRESULT, Error code.
  881. //
  882. // Author: danielwe 21 Mar 1997
  883. //
  884. // Notes:
  885. //
  886. HRESULT CNetCfgIdentification::HrJoinWorkgroup()
  887. {
  888. HRESULT hr = S_OK;
  889. PCWSTR wszComputerName = NULL;
  890. AssertSz(m_szwNewDWName &&
  891. GetNewJoinStatus() == NetSetupWorkgroupName,
  892. "If there was no workgroup name, why'd you call me?!");
  893. // If the user has changed the computer name, use it, otherwise get the
  894. // current computer name and use that.
  895. hr = HrGetNewestComputerName(&wszComputerName);
  896. if (FAILED(hr))
  897. goto err;
  898. AssertSz(wszComputerName, "We don't have a computer name!");
  899. hr = HrEnsureCurrentDomainOrWorkgroupName();
  900. if (FAILED(hr))
  901. goto err;
  902. if (FIsJoinedToDomain())
  903. {
  904. // Must unjoin from domain if currently joined.
  905. // If currently joined to a workgroup, this is not necessary.
  906. hr = HrNetUnjoinDomain(m_szwUserName, m_szwPassword, 0);
  907. if (FAILED(hr))
  908. goto err;
  909. // Free username and password
  910. DeleteStringAndSetNull(&m_szwPassword);
  911. DeleteStringAndSetNull(&m_szwUserName);
  912. }
  913. // Go ahead and join the workgroup
  914. hr = HrNetJoinDomain(const_cast<PWSTR>(wszComputerName),
  915. m_szMachineObjectOU,
  916. m_szwNewDWName, NULL, NULL, 0);
  917. if (FAILED(hr))
  918. goto err;
  919. // Make the current workgroup name the new one since the join on the
  920. // new workgroup has succeeded
  921. hr = HrEstablishNewDomainOrWorkgroupName(NetSetupWorkgroupName);
  922. if (FAILED(hr))
  923. goto err;
  924. err:
  925. TraceError("CNetCfgIdentification::HrJoinWorkgroup", hr);
  926. return hr;
  927. }
  928. //+---------------------------------------------------------------------------
  929. //
  930. // Member: CNetCfgIdentification::JoinWorkgroup
  931. //
  932. // Purpose: Implements COM interface to join this computer to a new
  933. // workgroup.
  934. //
  935. // Arguments:
  936. // szwWorkgroup [in] Name of new workgroup to join.
  937. //
  938. // Returns: HRESULT, Error code.
  939. //
  940. // Author: danielwe 21 Mar 1997
  941. //
  942. // Notes: Validates, but does not actually join the workgroup. Only holds
  943. // onto the information until Apply() is called.
  944. //
  945. STDMETHODIMP CNetCfgIdentification::JoinWorkgroup(PCWSTR szwWorkgroup)
  946. {
  947. HRESULT hr = S_OK;
  948. Validate_INetCfgIdentification_JoinWorkgroup(szwWorkgroup);
  949. COM_PROTECT_TRY
  950. {
  951. hr = HrValidateWorkgroupName(szwWorkgroup);
  952. if (FAILED(hr))
  953. goto err;
  954. // Free domain and password given if JoinDomain was called previously
  955. DeleteStringAndSetNull(&m_szwPassword);
  956. DeleteStringAndSetNull(&m_szwUserName);
  957. // Assign in new workgroup name.
  958. m_szwNewDWName = SzDupSz(szwWorkgroup);
  959. m_jsNew = NetSetupWorkgroupName;
  960. }
  961. COM_PROTECT_CATCH;
  962. err:
  963. TraceError("CNetCfgIdentification::JoinWorkgroup", hr);
  964. return hr;
  965. }
  966. //+---------------------------------------------------------------------------
  967. //
  968. // Member: CNetCfgIdentification::HrEstablishNewDomainOrWorkgroupName
  969. //
  970. // Purpose: When the computer is joined to a new domain or workgroup, this
  971. // function is called to set the correct member variables and
  972. // free the old ones.
  973. //
  974. // Arguments:
  975. // js [in] Indicates whether the computer is joined to a domain or
  976. // workgroup.
  977. //
  978. // Returns: S_OK, or E_OUTOFMEMORY.
  979. //
  980. // Author: danielwe 1 Apr 1997
  981. //
  982. // Notes: Replaces the m_szwCurDWName variable with the new one
  983. // (m_szwNewDWName).
  984. //
  985. HRESULT CNetCfgIdentification::HrEstablishNewDomainOrWorkgroupName(
  986. NETSETUP_JOIN_STATUS js)
  987. {
  988. HRESULT hr = S_OK;
  989. // Make the current domain or workgroup name the new one.
  990. DeleteStringAndSetNull(&m_szwCurDWName);
  991. m_szwCurDWName = SzDupSz(m_szwNewDWName);
  992. m_jsCur = js;
  993. AssertSz(GetCurrentJoinStatus() == NetSetupWorkgroupName ||
  994. GetCurrentJoinStatus() == NetSetupDomainName,
  995. "Invalid join status flag!");
  996. // Free "new" name
  997. DeleteStringAndSetNull(&m_szwNewDWName);
  998. // Also make sure that we don't have a "new" join status either
  999. m_jsNew = NetSetupUnjoined;
  1000. TraceError("CNetCfgIdentification::HrEstablishNewDomainOrWorkgroupName",
  1001. hr);
  1002. return hr;
  1003. }
  1004. //+---------------------------------------------------------------------------
  1005. //
  1006. // Member: CNetCfgIdentification::HrJoinDomain
  1007. //
  1008. // Purpose: Actually performs the JoinDomain function.
  1009. //
  1010. // Arguments:
  1011. // (none)
  1012. //
  1013. // Returns: HRESULT, Error code.
  1014. //
  1015. // Author: danielwe 21 Mar 1997
  1016. //
  1017. // Notes:
  1018. //
  1019. HRESULT CNetCfgIdentification::HrJoinDomain()
  1020. {
  1021. HRESULT hr = S_OK;
  1022. PCWSTR wszComputerName = NULL;
  1023. DWORD dwJoinOption = 0;
  1024. BOOL fIsRename = FALSE;
  1025. BOOL fUseNulls = FALSE;
  1026. AssertSz(m_szwNewDWName && m_jsNew == NetSetupDomainName,
  1027. "If there was no domain name, why'd you call me?!");
  1028. AssertSz(FImplies(m_szwPassword,
  1029. m_szwUserName),
  1030. "Password without username!!");
  1031. // If the user has changed the computer name, use it, otherwise get the
  1032. // current computer name and use that.
  1033. hr = HrGetNewestComputerName(&wszComputerName);
  1034. if (FAILED(hr))
  1035. goto err;
  1036. {
  1037. AssertSz(wszComputerName == m_szwCurComputerName, "If I don't have a "
  1038. "new computer name, this better be the original one!");
  1039. dwJoinOption |= NETSETUP_JOIN_DOMAIN;
  1040. }
  1041. AssertSz(wszComputerName, "We don't have a computer name!");
  1042. AssertSz(dwJoinOption, "No option was set??");
  1043. AssertSz(FImplies(m_szwPassword,
  1044. m_szwUserName),
  1045. "Password without username!");
  1046. // Create a machine account if so asked.
  1047. if (m_dwJoinFlags & JDF_CREATE_ACCOUNT)
  1048. {
  1049. dwJoinOption |= NETSETUP_ACCT_CREATE;
  1050. }
  1051. if (m_dwJoinFlags & JDF_WIN9x_UPGRADE)
  1052. {
  1053. dwJoinOption |= NETSETUP_WIN9X_UPGRADE;
  1054. }
  1055. if (m_dwJoinFlags & JDF_JOIN_UNSECURE)
  1056. {
  1057. dwJoinOption |= NETSETUP_JOIN_UNSECURE;
  1058. }
  1059. #if defined(REMOTE_BOOT)
  1060. // TEMP: On a remote boot machine, prevent machine password change
  1061. if (HrIsRemoteBootMachine() == S_OK)
  1062. {
  1063. TraceTag (ttidNetcfgBase,
  1064. "Machine is remote boot, specifying WIN9X_UPGRADE flag to JoinDomain.");
  1065. dwJoinOption |= NETSETUP_WIN9X_UPGRADE;
  1066. }
  1067. #endif // defined(REMOTE_BOOT)
  1068. //$ REVIEW (danielwe) 2 Apr 1997: If new domain is same as old, unjoin
  1069. // then rejoin??
  1070. if (!(fIsRename) && FIsJoinedToDomain())
  1071. {
  1072. // Must unjoin from domain if currently joined.
  1073. // If currently joined to a workgroup, this is not necessary.
  1074. // Also we don't unjoin if we are renaming the machine in the domain.
  1075. hr = HrNetUnjoinDomain(m_szwUserName,
  1076. m_szwPassword, 0);
  1077. if (FAILED(hr))
  1078. goto err;
  1079. }
  1080. if (FInSystemSetup())
  1081. {
  1082. // During system setup, need to pass special flag that tells join code
  1083. // to not do certain operations because SAM is not initialized yet.
  1084. dwJoinOption |= NETSETUP_INSTALL_INVOCATION;
  1085. }
  1086. // If the supplied username has astring length of zero, then the join
  1087. // API's should be called with NULL's.
  1088. //
  1089. if ((NULL == m_szwUserName) || (0 == wcslen(m_szwUserName)))
  1090. {
  1091. fUseNulls = TRUE;
  1092. }
  1093. // Go ahead and join the domain
  1094. if( fIsRename) {
  1095. hr = HrNetRenameInDomain(const_cast<PWSTR>(wszComputerName),
  1096. m_szwNewDWName,
  1097. (fUseNulls ? NULL : m_szwUserName),
  1098. (fUseNulls ? NULL : m_szwPassword),
  1099. dwJoinOption);
  1100. } else {
  1101. hr = HrNetJoinDomain(const_cast<PWSTR>(wszComputerName),
  1102. m_szMachineObjectOU,
  1103. m_szwNewDWName,
  1104. (fUseNulls ? NULL : m_szwUserName),
  1105. (fUseNulls ? NULL : m_szwPassword),
  1106. dwJoinOption);
  1107. }
  1108. if (FAILED(hr))
  1109. {
  1110. // Note: (danielwe) Making assumption that failure to join a domain puts us in
  1111. // a workgroup. MacM owns the code responsible for this.
  1112. m_jsCur = NetSetupWorkgroupName;
  1113. goto err;
  1114. }
  1115. // Make the current domain name the new one since the join on the
  1116. // new domain has succeeded
  1117. hr = HrEstablishNewDomainOrWorkgroupName(NetSetupDomainName);
  1118. if (FAILED(hr))
  1119. goto err;
  1120. err:
  1121. // Free username and password
  1122. DeleteStringAndSetNull(&m_szwPassword);
  1123. DeleteStringAndSetNull(&m_szwUserName);
  1124. TraceError("CNetCfgIdentification::HrJoinDomain", hr);
  1125. return hr;
  1126. }
  1127. //+---------------------------------------------------------------------------
  1128. //
  1129. // Member: CNetCfgIdentification::JoinDomain
  1130. //
  1131. // Purpose: Implements COM interface to join this computer to a new
  1132. // domain.
  1133. //
  1134. // Arguments:
  1135. // szwDomain [in] New domain name.
  1136. // szMachineObjectOU [in] Machine object OU (optional)
  1137. // szwUserName [in] User name to use in validation.
  1138. // szwPassword [in] Password to use in validation.
  1139. // dwJoinFlags [in] Currently can be 0 or JDF_CREATE_ACCOUNT.
  1140. //
  1141. // Returns: HRESULT, Error code.
  1142. //
  1143. // Author: danielwe 21 Mar 1997
  1144. //
  1145. // Notes: Validates, but does not actually join the domain. Only holds
  1146. // onto the information until Apply() is called.
  1147. //
  1148. STDMETHODIMP CNetCfgIdentification::JoinDomain(PCWSTR szwDomain,
  1149. PCWSTR szMachineObjectOU,
  1150. PCWSTR szwUserName,
  1151. PCWSTR szwPassword,
  1152. DWORD dwJoinFlags)
  1153. {
  1154. HRESULT hr = S_OK;
  1155. static const WCHAR c_wszBackslash[] = L"\\";
  1156. static const WCHAR c_wszAt[] = L"@";
  1157. COM_PROTECT_TRY
  1158. {
  1159. Validate_INetCfgIdentification_JoinDomain(szwDomain, szwUserName,
  1160. szwPassword);
  1161. #if defined(REMOTE_BOOT)
  1162. if (HrIsRemoteBootMachine() == S_FALSE)
  1163. #endif // defined(REMOTE_BOOT)
  1164. {
  1165. // look for non-empty password and empty username or username
  1166. // consisting of only the backslash character
  1167. if (!FIsStrEmpty(szwPassword) && FIsStrEmpty(szwUserName) ||
  1168. !lstrcmpW(szwUserName, c_wszBackslash))
  1169. {
  1170. // Password without username is invalid.
  1171. hr = E_INVALIDARG;
  1172. goto err;
  1173. }
  1174. PWSTR wszNewUserName;
  1175. INT cchNewUserName;
  1176. // Check if username that was passed in has a backslash in it or
  1177. // an '@', or if it is empty.
  1178. if (FIsStrEmpty(szwUserName) ||
  1179. wcschr(szwUserName, c_wszBackslash[0]) ||
  1180. wcschr(szwUserName, c_wszAt[0]))
  1181. {
  1182. // if so, don't do anything extra
  1183. wszNewUserName = NULL;
  1184. }
  1185. else
  1186. {
  1187. // if not, we have to append the domain name to the username
  1188. cchNewUserName = lstrlenW(szwUserName) + // original username
  1189. lstrlenW(szwDomain) + // domain name
  1190. 1 + // backslash character
  1191. 1; // terminating NULL
  1192. wszNewUserName = new WCHAR[cchNewUserName];
  1193. if(wszNewUserName)
  1194. {
  1195. // Turn username into domain\username format
  1196. lstrcpyW(wszNewUserName, szwDomain);
  1197. lstrcatW(wszNewUserName, c_wszBackslash);
  1198. lstrcatW(wszNewUserName, szwUserName);
  1199. AssertSz(lstrlenW(wszNewUserName) + 1 == cchNewUserName,
  1200. "Possible memory overwrite in username!");
  1201. }
  1202. }
  1203. // Use wszNewUserName if non-NULL, otherwise use szwUserName
  1204. PCWSTR szwUserNameToCopy;
  1205. szwUserNameToCopy = wszNewUserName ? wszNewUserName : szwUserName;
  1206. m_szwUserName = SzDupSz(szwUserNameToCopy);
  1207. m_szwPassword = SzDupSz(szwPassword);
  1208. delete [] wszNewUserName;
  1209. }
  1210. AssertSz(FImplies(m_szwPassword,
  1211. m_szwUserName),
  1212. "Password without username!");
  1213. hr = HrValidateDomainName(szwDomain, m_szwUserName, m_szwPassword);
  1214. if (FAILED(hr))
  1215. goto err;
  1216. // Assign in new strings
  1217. m_szwNewDWName = SzDupSz(szwDomain);
  1218. if (szMachineObjectOU)
  1219. {
  1220. m_szMachineObjectOU = SzDupSz(szMachineObjectOU);
  1221. }
  1222. m_dwJoinFlags = dwJoinFlags;
  1223. m_jsNew = NetSetupDomainName;
  1224. err:
  1225. // suppress compiler error
  1226. ;
  1227. }
  1228. COM_PROTECT_CATCH;
  1229. TraceError("CNetCfgIdentification::JoinDomain", hr);
  1230. return hr;
  1231. }
  1232. //+---------------------------------------------------------------------------
  1233. //
  1234. // Member: CNetCfgIdentification::GetComputerRole
  1235. //
  1236. // Purpose: Returns the current role of the computer.
  1237. //
  1238. // Arguments:
  1239. // pdwRoleFlags [out] Returns value which determines the role of this
  1240. // computer.
  1241. //
  1242. // Returns: S_OK if success, error code otherwise.
  1243. //
  1244. // Author: danielwe 26 Mar 1997
  1245. //
  1246. // Notes: Returned role can be one of:
  1247. // SERVER_STANDALONE - The machine is part of a workgroup.
  1248. // SERVER_MEMBER - The machine is joined to the domain.
  1249. // SERVER_PDC - The machine is a primary domain controller.
  1250. // SERVER_BDC - The machine is a backup domain controller.
  1251. //
  1252. STDMETHODIMP CNetCfgIdentification::GetComputerRole(DWORD* pdwRoleFlags)
  1253. {
  1254. HRESULT hr = S_OK;
  1255. Validate_INetCfgIdentification_GetComputerRole(pdwRoleFlags);
  1256. COM_PROTECT_TRY
  1257. {
  1258. *pdwRoleFlags = 0;
  1259. hr = HrEnsureCurrentDomainOrWorkgroupName();
  1260. if (SUCCEEDED(hr))
  1261. {
  1262. if (m_jsNew == NetSetupUnjoined)
  1263. {
  1264. // The workgroup or domain has not been changed since this
  1265. // object was instantiated
  1266. if (GetCurrentJoinStatus() == NetSetupDomainName)
  1267. {
  1268. *pdwRoleFlags = GCR_MEMBER;
  1269. }
  1270. else if (GetCurrentJoinStatus() == NetSetupWorkgroupName)
  1271. {
  1272. *pdwRoleFlags = GCR_STANDALONE;
  1273. }
  1274. #ifdef DBG
  1275. else
  1276. {
  1277. AssertSz(FALSE, "Invalid join status flag!");
  1278. }
  1279. #endif
  1280. }
  1281. else
  1282. {
  1283. // This means the workgroup or domain name has been changed
  1284. // since this object was instantiated
  1285. if (GetNewJoinStatus() == NetSetupDomainName)
  1286. {
  1287. *pdwRoleFlags = GCR_MEMBER;
  1288. }
  1289. else if (GetNewJoinStatus() == NetSetupWorkgroupName)
  1290. {
  1291. *pdwRoleFlags = GCR_STANDALONE;
  1292. }
  1293. #ifdef DBG
  1294. else
  1295. {
  1296. AssertSz(FALSE, "Invalid join status flag!");
  1297. }
  1298. #endif
  1299. }
  1300. }
  1301. }
  1302. COM_PROTECT_CATCH;
  1303. TraceError("CNetCfgIdentification::GetComputerRole", hr);
  1304. return hr;
  1305. }