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.

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