netwiz.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 33k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. #include "stdafx.h"
  2. #include "shlobj.h"
  3. #include "shlobjp.h"
  4. #include "shsemip.h"
  5. // Headers for the group list and group page base
  6. #include "grpinfo.h"
  7. #include "grppage.h"
  8. #pragma hdrstop
  9. //
  10. // useful globals and macros used by everybody
  11. //
  12. DWORD g_dwWhichNet;
  13. UINT g_uWizardIs = NAW_NETID; 
  14. BOOL g_fRebootOnExit = FALSE;
  15. BOOL g_fShownLastPage = FALSE;
  16. // Stuff for creating a default autologon user
  17. #define ITEMDATA_DEFAULTLOCALUSER   0xDEADBEEF
  18. const WCHAR c_szAdminAccount[] = L"Administrator";
  19. //
  20. // The wizard pages we are adding
  21. //
  22. #define WIZDLG(name, dlgproc, dwFlags)   
  23.             { MAKEINTRESOURCE(IDD_PSW_##name##), dlgproc, MAKEINTRESOURCE(IDS_##name##), MAKEINTRESOURCE(IDS_##name##_SUB), dwFlags }
  24. struct
  25. {
  26.     LPCWSTR idPage;
  27.     DLGPROC pDlgProc;
  28.     LPCWSTR pHeading;
  29.     LPCWSTR pSubHeading;
  30.     DWORD dwFlags;
  31. }
  32. pages[] =
  33. {    
  34.     WIZDLG(WELCOME,     _IntroDlgProc,       PSP_HIDEHEADER),
  35.     WIZDLG(HOWUSE,      _HowUseDlgProc,      0),
  36.     WIZDLG(WHICHNET,    _WhichNetDlgProc,    0),
  37.     WIZDLG(DOMAININFO,  _DomainInfoDlgProc,  0),
  38.     WIZDLG(USERINFO,    _UserInfoDlgProc,    0),
  39.     WIZDLG(COMPINFO,    _CompInfoDlgProc,    0),
  40.     WIZDLG(ADDUSER,     _AddUserDlgProc,     0),
  41.     WIZDLG(PERMISSIONS, _PermissionsDlgProc, 0),
  42.     WIZDLG(WORKGROUP,   _WorkgroupDlgProc,   0),
  43.     WIZDLG(AUTOLOGON,   _AutoLogonDlgProc,   0),
  44.     WIZDLG(DONE,        _DoneDlgProc,        PSP_HIDEHEADER), 
  45. };
  46. //
  47. // Set the Wizard buttons for the dialog
  48. //
  49. void SetWizardButtons(HWND hwndPage, DWORD dwButtons)
  50. {
  51.     HWND hwndParent = GetParent(hwndPage);
  52.     if ( g_uWizardIs != NAW_NETID )
  53.     {
  54. #if 0 
  55.         EnableWindow(GetDlgItem(hwndParent,IDCANCEL),FALSE);
  56.         ShowWindow(GetDlgItem(hwndParent,IDCANCEL),SW_HIDE);
  57. #endif
  58.         EnableWindow(GetDlgItem(hwndParent,IDHELP),FALSE);
  59.         ShowWindow(GetDlgItem(hwndParent,IDHELP),SW_HIDE);
  60.     }
  61.     if ( g_fRebootOnExit ) 
  62.     {
  63.         TCHAR szBuffer[80];
  64.         LoadString(GLOBAL_HINSTANCE, IDS_CLOSE, szBuffer, ARRAYSIZE(szBuffer));
  65.         SetDlgItemText(hwndParent, IDCANCEL, szBuffer);
  66.     }
  67.     
  68.     PropSheet_SetWizButtons(hwndParent, dwButtons);
  69. }
  70. // Utility fn's
  71. // GetRegisteredOwner - retrieves the name of the registered owner
  72. // of the machine
  73. HRESULT GetRegisteredOwner(TCHAR* pszOwner, DWORD cchOwner)
  74. {
  75.     // REGKEY for Registered Owner (HKLM)
  76.     static const TCHAR c_szRegOwnerKey[] = TEXT("Software\Microsoft\Windows NT\CurrentVersion");
  77.     static const TCHAR c_szRegOwnerVal[] = TEXT("RegisteredOwner");
  78.     // Default to failure
  79.     HRESULT hr = E_FAIL;
  80.     LONG Err;
  81.     
  82.     HKEY hkey;
  83.     Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegOwnerKey, 0, KEY_QUERY_VALUE, &hkey);
  84.     if (ERROR_SUCCESS == Err)
  85.     {
  86.         DWORD cbBuffer = cchOwner * sizeof(TCHAR);
  87.         DWORD dwType;
  88.         Err = RegQueryValueEx(hkey, c_szRegOwnerVal, 0, &dwType,
  89.             (LPBYTE) pszOwner, &cbBuffer);
  90.         if (ERROR_SUCCESS == Err)
  91.         {
  92.             hr = S_OK;
  93.         }
  94.         RegCloseKey(hkey);
  95.     }
  96.     return hr;
  97. }
  98. inline BOOL IsLegalNameCharacter(WCHAR ch)
  99. {
  100.     // We need to use illegal fat chars, says SBurns
  101.     return (NULL == StrChr(ILLEGAL_FAT_CHARS, ch));
  102. }
  103. // Create a username from a source string by removing all non-alphabetic chars
  104. HRESULT MungeUserName(TCHAR* pszSource, TCHAR* pszUsername, DWORD cchUsername)
  105. {
  106.     DWORD ichDest = 0;
  107.     // Examine each char in the source string as long as there is room left
  108.     // in the destination buffer for the next char and a null-terminator
  109.     for (DWORD ichSrc = 0; ((TEXT('') != pszSource[ichSrc]) && (ichDest < (cchUsername-1))); ichSrc++)
  110.     {
  111.         TCHAR ch = pszSource[ichSrc];
  112.         // Is character allowed?
  113.         if (IsLegalNameCharacter(ch)) 
  114.         {
  115.             // it is, add it to the string
  116.             pszUsername[ichDest ++] = ch;
  117.         }
  118.     }
  119.     // Null-terminate
  120.     if (cchUsername != 0)
  121.     {
  122.         pszUsername[ichDest] = TEXT('');
  123.         // If we have room on the string for one more character before the null
  124.         if (ichDest < (cchUsername-1))
  125.         {
  126.             // If the generated name matches the computer name
  127.             TCHAR szComputer[MAX_COMPUTERNAME + 1];
  128.             DWORD cchComputer = ARRAYSIZE(szComputer);
  129.             if (GetComputerName(szComputer, &cchComputer))
  130.             {
  131.                 if (0 == lstrcmpi(szComputer, pszUsername))
  132.                 {
  133.                     // Yes, names are the same. Then we need to munge the name just a bit more so they are different
  134.                     // Add a '1' to the end of the string
  135.                     pszUsername[ichDest++] = TEXT('1');
  136.                     pszUsername[ichDest] = TEXT('');
  137.                 }
  138.             }    
  139.         }
  140.     }
  141.     return (ichDest > 0) ? S_OK : E_FAIL;
  142. }
  143. HRESULT GetDefaultLocalUserName(TCHAR* szUser, DWORD cchUser)
  144. {
  145.     HRESULT hr = E_UNEXPECTED;
  146.     // Name of the registered owner of this machine - we'll munge
  147.     // a username from this
  148.     TCHAR szRegisteredOwner[256];
  149.     hr = GetRegisteredOwner(szRegisteredOwner, ARRAYSIZE(szRegisteredOwner));
  150.     if (SUCCEEDED(hr))
  151.     {
  152.         // Allowing for only alphabetic characters, turn the registered
  153.         // owners name into a username of no more than MAX_USER chars
  154.         hr = MungeUserName(szRegisteredOwner, szUser, cchUser);
  155.     }
  156.     return hr;
  157. }
  158. BOOL GetAdministratorsGroupName(TCHAR* pszAdmins, DWORD cchAdmins)
  159. {
  160.     PSID psid;
  161.     SID_IDENTIFIER_AUTHORITY auth = SECURITY_NT_AUTHORITY;
  162.     BOOL fSuccess = AllocateAndInitializeSid(
  163.         &auth,
  164.         2,
  165.         SECURITY_BUILTIN_DOMAIN_RID,
  166.         DOMAIN_ALIAS_RID_ADMINS,
  167.         0,0,0,0,0,0,
  168.         &psid
  169.         );
  170.     if (fSuccess)
  171.     {
  172.         TCHAR szDomain[DNLEN + 1];
  173.         DWORD cchDomain = ARRAYSIZE(szDomain);
  174.         SID_NAME_USE sUse;
  175.         fSuccess = LookupAccountSid(NULL, psid, pszAdmins, &cchAdmins, szDomain, &cchDomain, &sUse);
  176.         FreeSid(psid);
  177.     }
  178.     return fSuccess;
  179. }
  180. // CreateLocalAdminUser - creates a local user account, puts this
  181. // user into the administrators group.
  182. HRESULT CreateLocalAdminUser(HWND hwnd, LPTSTR szUser, LPTSTR szPassword)
  183. {
  184.     HRESULT hr;
  185.     // Create a user account
  186.     // *********************
  187. #ifdef DONT_JOIN
  188.     hr = S_OK;
  189. #else // !DONT_JOIN
  190.     // Assume failure
  191.     hr = E_FAIL;
  192.     // Try to add this user to the system and put them in the administrators group
  193.     USER_INFO_1 usri1;
  194.     usri1.usri1_name = szUser;
  195.     usri1.usri1_password = szPassword;
  196.     usri1.usri1_password_age = 0;
  197.     usri1.usri1_priv = USER_PRIV_USER;
  198.     usri1.usri1_home_dir = L"";
  199.     usri1.usri1_comment = L"";
  200.     usri1.usri1_flags  = UF_DONT_EXPIRE_PASSWD | UF_NORMAL_ACCOUNT;
  201.     usri1.usri1_script_path = NULL;
  202.     NET_API_STATUS status = NetUserAdd(NULL, 1, (LPBYTE) &usri1, NULL);
  203.     if (NERR_Success == status)
  204.     {
  205.         // Set the user's full name (easier than using USER_INFO_2)
  206.         USER_INFO_1011 usri1011;
  207.         TCHAR szRegisteredOwner[256];
  208.         if (SUCCEEDED(GetRegisteredOwner(szRegisteredOwner, ARRAYSIZE(szRegisteredOwner))))
  209.         {
  210.             usri1011.usri1011_full_name = szRegisteredOwner;
  211.             NetUserSetInfo(NULL, szUser, 1011, (LPBYTE) &usri1011, NULL);
  212.         }
  213.         // Add to administrators group
  214.         // ***************************
  215. TCHAR szAdmins[GNLEN + 1];
  216.         if (GetAdministratorsGroupName(szAdmins, ARRAYSIZE(szAdmins)))
  217.         {
  218.             LOCALGROUP_MEMBERS_INFO_3 lgrmi3;
  219.             lgrmi3.lgrmi3_domainandname = szUser;
  220.             status = NetLocalGroupAddMembers(NULL, szAdmins, 3, 
  221.                 (LPBYTE) &lgrmi3, 1);
  222.             if (NERR_Success != status)
  223.             {
  224.                 // Failure - Roll-back
  225.                 // *******************
  226.                 // Delete this user since we couldn't add
  227.                 // them to administrators
  228.                 NetUserDel(NULL, szUser);
  229.             }
  230.         }
  231.     }
  232.     // Did we succeed? If not, show an error
  233.     switch ( status )
  234.     {
  235.         // Success conditions
  236.         case NERR_Success:
  237.         case ERROR_MEMBER_IN_GROUP:
  238.         case ERROR_MEMBER_IN_ALIAS:
  239.         {
  240.             hr = S_OK;
  241.             break;
  242.         }
  243.         default:
  244.         {
  245.             // Unexpected error
  246.             TCHAR szMessage[512];
  247.             DWORD dwFormatResult = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, (DWORD) status, 0, szMessage, ARRAYSIZE(szMessage), NULL);
  248.             if (0 == dwFormatResult)
  249.             {
  250.                 LoadString(g_hInstance, IDS_ERR_UNEXPECTED, szMessage, ARRAYSIZE(szMessage));
  251.             }
  252.             ::DisplayFormatMessage(hwnd, IDS_ERR_CAPTION, IDS_ERR_ADDUSER, MB_OK|MB_ICONERROR, szMessage);
  253.             hr = E_FAIL;
  254.             break;
  255.         }
  256.     }
  257. #endif //DONT_JOIN
  258.     return hr;
  259. }
  260. /*-----------------------------------------------------------------------------
  261. / Intro page to the wizard.
  262. /----------------------------------------------------------------------------*/
  263. INT_PTR CALLBACK _IntroDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  264. {
  265.     switch ( uMsg )
  266.     {
  267.         case WM_INITDIALOG:
  268.         {
  269.             SendDlgItemMessage(hwnd, IDC_TITLE, WM_SETFONT, (WPARAM)GetIntroFont(hwnd), 0);
  270.             return TRUE;
  271.         }
  272.         case WM_NOTIFY:
  273.         {
  274.             LPNMHDR pnmh = (LPNMHDR)lParam;             
  275.             switch (pnmh->code)
  276.             {
  277.                 case PSN_SETACTIVE:            
  278.                     SetWizardButtons(hwnd, PSWIZB_NEXT);
  279.                     return TRUE;              
  280.                 case PSN_WIZNEXT:
  281.                 {
  282.                     switch ( g_uWizardIs )
  283.                     {
  284.                     case NAW_PSDOMAINJOINED:
  285.                         WizardNext(hwnd, IDD_PSW_ADDUSER);
  286.                         break;
  287.                     case NAW_PSWORKGROUP:
  288.                         WizardNext(hwnd, IDD_PSW_AUTOLOGON);
  289.                         break;
  290.                     default:
  291.                         // Let the wizard go to the next page
  292.                         break;
  293.                     }
  294.                         
  295.                     return TRUE;
  296.                 }
  297.             }
  298.             break;
  299.         }
  300.     }
  301.     return FALSE;
  302. }                                    
  303. /*-----------------------------------------------------------------------------
  304. / Get the usage of the computer: corp vs home
  305. /----------------------------------------------------------------------------*/
  306. INT_PTR CALLBACK _HowUseDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  307. {
  308.     switch ( uMsg )
  309.     {
  310.         case WM_INITDIALOG:
  311.             CheckRadioButton(hwnd, IDC_NETWORKED, IDC_NOTNETWORKED, IDC_NETWORKED);
  312.             return TRUE;
  313.     
  314.         case WM_NOTIFY:
  315.         {
  316.             LPNMHDR pnmh = (LPNMHDR)lParam;             
  317.             switch (pnmh->code)
  318.             {
  319.                 case PSN_SETACTIVE:            
  320.                     SetWizardButtons(hwnd, PSWIZB_NEXT|PSWIZB_BACK);
  321.                     return TRUE;              
  322.                 case PSN_WIZBACK:
  323.                     WizardNext(hwnd, IDD_PSW_WELCOME);
  324.                     return TRUE;
  325.                 case PSN_WIZNEXT:
  326.                 {                    
  327.                     if ( IsDlgButtonChecked(hwnd, IDC_NETWORKED) == BST_CHECKED )
  328.                     {
  329.                         WizardNext(hwnd, IDD_PSW_WHICHNET);
  330.                     }
  331.                     else
  332.                     {
  333.                         g_dwWhichNet = IDC_NONE;
  334.                         if ( SUCCEEDED(JoinDomain(hwnd, FALSE, DEFAULT_WORKGROUP, NULL)) )
  335.                             WizardNext(hwnd, IDD_PSW_AUTOLOGON);
  336.                         else
  337.                             WizardNext(hwnd, -1);
  338.                     }
  339.                     return TRUE;
  340.                 }
  341.             }
  342.             break;
  343.         }
  344.     }
  345.     return FALSE;
  346. }
  347. /*-----------------------------------------------------------------------------
  348. / Determine what sort of networking the user wants to use (domain, workgroup
  349. / or none).
  350. /
  351. /----------------------------------------------------------------------------*/
  352. INT_PTR CALLBACK _WhichNetDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  353. {
  354.     switch ( uMsg )
  355.     {
  356.         case WM_INITDIALOG:
  357.             CheckRadioButton(hwnd, IDC_DOMAIN, IDC_WORKGROUP, IDC_DOMAIN);
  358.             return TRUE;
  359.     
  360.         case WM_NOTIFY:
  361.         {
  362.             LPNMHDR pnmh = (LPNMHDR)lParam;             
  363.             switch (pnmh->code)
  364.             {
  365.                 case PSN_SETACTIVE:            
  366.                     SetWizardButtons(hwnd, PSWIZB_NEXT|PSWIZB_BACK);
  367.                     return TRUE;              
  368.                 case PSN_WIZBACK:
  369.                     WizardNext(hwnd, IDD_PSW_HOWUSE);
  370.                     return TRUE;
  371.                 case PSN_WIZNEXT:
  372.                 {                    
  373.                     if ( IsDlgButtonChecked(hwnd, IDC_DOMAIN) == BST_CHECKED )
  374.                     {
  375.                         g_dwWhichNet = IDC_DOMAIN;
  376.                         WizardNext(hwnd, IDD_PSW_DOMAININFO);
  377.                     }
  378.                     else
  379.                     {
  380.                         g_dwWhichNet = IDC_WORKGROUP;
  381.                         WizardNext(hwnd, IDD_PSW_WORKGROUP);
  382.                     }
  383.                     return TRUE;
  384.                 }
  385.             }
  386.             break;
  387.         }
  388.     }
  389.     return FALSE;
  390. }
  391. /*-----------------------------------------------------------------------------
  392. / Allow the user to change the workgroup name.
  393. /----------------------------------------------------------------------------*/
  394. BOOL _WorkgroupBtnState(HWND hwnd)
  395. {
  396.     DWORD dwButtons = PSWIZB_NEXT|PSWIZB_BACK;
  397.     if ( !FetchTextLength(hwnd, IDC_WORKGROUP) )
  398.         dwButtons &= ~PSWIZB_NEXT;
  399.     SetWizardButtons(hwnd, dwButtons);
  400.     return TRUE;
  401. }
  402. INT_PTR CALLBACK _WorkgroupDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  403. {
  404.     switch ( uMsg )
  405.     {
  406.         case WM_INITDIALOG:
  407.         {
  408.             Edit_LimitText(GetDlgItem(hwnd, IDC_WORKGROUP), MAX_COMPUTERNAME);
  409.             SetDlgItemText(hwnd, IDC_WORKGROUP, DEFAULT_WORKGROUP);
  410.             return TRUE;
  411.         }
  412.         case WM_NOTIFY:
  413.         {
  414.             LPNMHDR pnmh = (LPNMHDR)lParam;             
  415.             switch (pnmh->code)
  416.             {
  417.                 case PSN_SETACTIVE:            
  418.                     return _WorkgroupBtnState(hwnd);
  419.                 case PSN_WIZBACK:
  420.                     WizardNext(hwnd, IDD_PSW_WHICHNET);
  421.                     return TRUE;
  422.                 case PSN_WIZNEXT:
  423.                 {
  424.                     WCHAR szWorkgroup[MAX_WORKGROUP+1];
  425.                     FetchText(hwnd, IDC_WORKGROUP, szWorkgroup, ARRAYSIZE(szWorkgroup));
  426.                     if ( SUCCEEDED(JoinDomain(hwnd, FALSE, szWorkgroup, NULL)) )
  427.                     {
  428.                         ClearAutoLogon();
  429.                         WizardNext(hwnd, IDD_PSW_DONE);
  430.                     }
  431.                     else
  432.                     {
  433.                         WizardNext(hwnd, -1);
  434.                     }
  435.                     return TRUE;
  436.                 }
  437.             }
  438.             break;
  439.         }
  440.         case WM_COMMAND:
  441.         {
  442.             if ( HIWORD(wParam) == EN_CHANGE )
  443.                 return _WorkgroupBtnState(hwnd);
  444.             break;
  445.         }
  446.     }
  447.     return FALSE;
  448. }
  449. /*-----------------------------------------------------------------------------
  450. / Handle the auto logon page
  451. /----------------------------------------------------------------------------*/
  452. VOID _SetAutoLogonCtrls(HWND hwnd)
  453. {
  454.     BOOL fDisable = IsDlgButtonChecked(hwnd, IDC_NOAUTOLOGON) == BST_CHECKED;
  455.     EnableWindow(GetDlgItem(hwnd, IDC_USERS), !fDisable);
  456.     EnableWindow(GetDlgItem(hwnd, IDC_USERSLABEL), !fDisable);
  457.     EnableWindow(GetDlgItem(hwnd, IDC_PASSWORD), !fDisable);
  458.     EnableWindow(GetDlgItem(hwnd, IDC_PASSWORDLABEL), !fDisable);
  459.     EnableWindow(GetDlgItem(hwnd, IDC_CONFIRMPASSWORD), !fDisable);
  460.     EnableWindow(GetDlgItem(hwnd, IDC_CONFIRMPASSWORDLABEL), !fDisable);
  461. }
  462. BOOL _InitAutoLogonDlg(HWND hwnd)
  463. {
  464.     HWND hwndUsers = GetDlgItem(hwnd, IDC_USERS);
  465.     NET_API_STATUS status;
  466.     USER_INFO_1 *pbuff;
  467.     DWORD dwResume = 0;
  468.     DWORD dwCount, dwEntries;
  469.     //
  470.     // set the auto logon state
  471.     //
  472.     CheckRadioButton(hwnd, IDC_NOAUTOLOGON, IDC_AUTOLOGON, (g_uWizardIs == NAW_PSWORKGROUP) ? IDC_AUTOLOGON : IDC_NOAUTOLOGON);
  473.     _SetAutoLogonCtrls(hwnd);
  474.     // 
  475.     // enumerate the local users of this machine and add them to the 
  476.     // combo box.
  477.     //
  478.     do 
  479.     {
  480.         status = NetUserEnum(NULL, 1, FILTER_NORMAL_ACCOUNT, (LPBYTE *)&pbuff, 8192, &dwCount, &dwEntries, &dwResume);
  481.         if ((status == NERR_Success) || (status == ERROR_MORE_DATA))
  482.         {
  483.             DWORD i;
  484.             for ( i = 0 ; i < dwCount ; i++ )
  485.             {
  486.                 if ( !(pbuff[i].usri1_flags & UF_ACCOUNTDISABLE) )
  487.                     ComboBox_AddString(hwndUsers, pbuff[i].usri1_name);
  488.             }
  489.             NetApiBufferFree(pbuff);
  490.         }
  491.     }
  492.     while ( dwCount != dwEntries );
  493.     // Select the first item, although we may override this with the default local user in a sec.
  494.     ComboBox_SetCurSel(hwndUsers, 0);
  495.     // If required, add the special default local user entry
  496.     if (g_uWizardIs == NAW_PSWORKGROUP)
  497.     {
  498.         // Add a special default local user string - user isn't actually created
  499.         // until Next is clicked.
  500.         TCHAR szUser[MAX_USER + 1];
  501.         if (SUCCEEDED(GetDefaultLocalUserName(szUser, ARRAYSIZE(szUser))))
  502.         {
  503.             // Don't add this user if he already exists. This is a weird situation since
  504.             // we only expect to run at first boot, but handle it anyway.
  505.             int iItem = ComboBox_FindStringExact(hwndUsers, -1, szUser);
  506.             
  507.             if (iItem == CB_ERR)
  508.             {
  509.                 iItem = ComboBox_AddString(hwndUsers, szUser);
  510.                 if (iItem != CB_ERR)
  511.                 {
  512.                     // Mark this item as the default local user guy.
  513.                     ComboBox_SetItemData(hwndUsers, iItem, ITEMDATA_DEFAULTLOCALUSER);
  514.                 }
  515.             }
  516.             if (iItem != CB_ERR)
  517.             {
  518.                 // Select it, its the default!
  519.                 ComboBox_SetCurSel(hwndUsers, iItem);
  520.             }
  521.         }
  522.     }
  523.     //
  524.     // limit the length of the password fields accordingly
  525.     //
  526.     Edit_LimitText(GetDlgItem(hwnd, IDC_PASSWORD), PWLEN);
  527.     Edit_LimitText(GetDlgItem(hwnd, IDC_CONFIRMPASSWORD), PWLEN);
  528.     
  529.     // 
  530.     // enable/disable buttons accordingly
  531.     //
  532.     _SetAutoLogonCtrls(hwnd);
  533.     return TRUE;
  534. }
  535. INT_PTR CALLBACK _AutoLogonDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  536. {
  537.     switch ( uMsg )
  538.     {
  539.         case WM_INITDIALOG:
  540.             return _InitAutoLogonDlg(hwnd);
  541.         case WM_COMMAND:
  542.         {
  543.             switch ( LOWORD(wParam) )
  544.             {
  545.                 case IDC_AUTOLOGON:
  546.                 case IDC_NOAUTOLOGON:
  547.                     _SetAutoLogonCtrls(hwnd);
  548.                     break;
  549.             } 
  550.             break;
  551.         }
  552.         case WM_NOTIFY:
  553.         {
  554.             LPNMHDR pnmh = (LPNMHDR)lParam;             
  555.             switch (pnmh->code)
  556.             {
  557.                 case PSN_QUERYINITIALFOCUS:
  558.                     // Set focus to the password control if we are going to try to do the autologon thing
  559.                     SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 
  560.                         (LONG_PTR) ((g_uWizardIs == NAW_PSWORKGROUP) ? GetDlgItem(hwnd, IDC_PASSWORD) : 0)
  561.                         );
  562.                     return TRUE;
  563.                 case PSN_SETACTIVE:            
  564.                     SetWizardButtons(hwnd, PSWIZB_BACK|PSWIZB_NEXT);
  565.                     return TRUE;              
  566.                 case PSN_WIZBACK:
  567.                 {
  568.                     switch ( g_dwWhichNet )
  569.                     {
  570.                         case IDC_WORKGROUP:
  571.                             WizardNext(hwnd, IDD_PSW_WORKGROUP);
  572.                             break;
  573.                         case IDC_NONE:
  574.                             WizardNext(hwnd, IDD_PSW_HOWUSE);
  575.                             break;
  576.                     }
  577.                     return TRUE;
  578.                 }
  579.                 case PSN_WIZNEXT:
  580.                 {
  581.                     WCHAR szUser[MAX_USER + 1] = { 0 };
  582.                     WCHAR szPassword[MAX_PASSWORD + 1] = { 0 };
  583.                     WCHAR szConfirmPwd[MAX_PASSWORD + 1] = { 0 };
  584.                     if ( IsDlgButtonChecked(hwnd, IDC_NOAUTOLOGON) == BST_CHECKED )
  585.                     {
  586.                         //
  587.                         // clear the auto admin logon
  588.                         //
  589.                         ClearAutoLogon();
  590.                     }
  591.                     else
  592.                     {
  593.                         //
  594.                         // read the two passwords, check they match, if then don't tell
  595.                         // the user clear them and prompt again.  if they do then
  596.                         // we can continue.
  597.                         //
  598.                         HWND hwndUsers = GetDlgItem(hwnd, IDC_USERS);
  599.                         ComboBox_GetText(hwndUsers, szUser, ARRAYSIZE(szUser));
  600.                         FetchText(hwnd, IDC_PASSWORD, szPassword, ARRAYSIZE(szPassword));
  601.                         FetchText(hwnd, IDC_CONFIRMPASSWORD, szConfirmPwd, ARRAYSIZE(szConfirmPwd));
  602.                 
  603.                         if ( StrCmpW(szPassword, szConfirmPwd) )
  604.                         {
  605.                             ShellMessageBox(GLOBAL_HINSTANCE, hwnd,
  606.                                             MAKEINTRESOURCE(IDS_ERR_PWDNOMATCH),
  607.                                             MAKEINTRESOURCE(IDS_AUTOLOGON),
  608.                                             MB_OK|MB_ICONWARNING);
  609.                             SetFocus(GetDlgItem(hwnd, IDC_PASSWORD));
  610.                             SetDlgItemText(hwnd, IDC_PASSWORD, L"");
  611.                             SetDlgItemText(hwnd, IDC_CONFIRMPASSWORD, L"");
  612.                             WizardNext(hwnd, -1);
  613.                         }
  614.                         else
  615.                         {
  616.                             // The passwords match - create the default local user if appropriate
  617.                             
  618.                             // Is this the default boy?
  619.                             HRESULT hr = S_OK;
  620.                             int iItem = ComboBox_GetCurSel(hwndUsers);
  621.                             if (iItem != CB_ERR)
  622.                             {
  623.                                 if (ITEMDATA_DEFAULTLOCALUSER == ComboBox_GetItemData(hwndUsers, iItem))
  624.                                 {
  625.                                     hr = CreateLocalAdminUser(hwnd, szUser, szPassword);
  626.                                 }
  627.                             }
  628.                             if (SUCCEEDED(hr))
  629.                             {
  630.                                 SetAutoLogon(szUser, szPassword);
  631.                                 WizardNext(hwnd, IDD_PSW_DONE);
  632.                             }
  633.                             else
  634.                             {
  635.                                 WizardNext(hwnd, -1);
  636.                             }
  637.                         }
  638.                     }
  639.                                        
  640.                     return TRUE;
  641.                 }
  642.             }
  643.             break;
  644.         }
  645.     }
  646.     return FALSE;
  647. }
  648. /*-----------------------------------------------------------------------------
  649. / The wizard is complete, so lets allow them to back up if they want,
  650. / otherwise "Next" becomes "Finish" and we exit.
  651. /----------------------------------------------------------------------------*/
  652. INT_PTR CALLBACK _DoneDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  653. {
  654.     switch ( uMsg )
  655.     {
  656.         case WM_INITDIALOG:
  657.             SendDlgItemMessage(hwnd, IDC_TITLE, WM_SETFONT, (WPARAM)GetIntroFont(hwnd), 0);
  658.             return TRUE;
  659.         case WM_NOTIFY:
  660.         {
  661.             LPNMHDR pnmh = (LPNMHDR)lParam;             
  662.             switch (pnmh->code)
  663.             {
  664.                 case PSN_SETACTIVE:            
  665.                 {
  666.                     TCHAR szBuffer[MAX_PATH];
  667.                     //
  668.                     // change the closing prompt if we are supposed to be
  669.                     //
  670.                     LoadString(GLOBAL_HINSTANCE, 
  671.                                g_fRebootOnExit ? IDS_NETWIZFINISHREBOOT:IDS_NETWIZFINISH, 
  672.                                szBuffer, ARRAYSIZE(szBuffer));
  673.             
  674.                     SetDlgItemText(hwnd, IDC_FINISHSTATIC, szBuffer);
  675.                     SetWizardButtons(hwnd, PSWIZB_BACK|PSWIZB_FINISH);
  676.                     g_fShownLastPage = TRUE;                    // show the last page of the wizard
  677.                     return TRUE;
  678.                 }
  679.                 case PSN_WIZBACK:
  680.                 {
  681.                     switch ( g_dwWhichNet )
  682.                     {
  683.                         case IDC_DOMAIN:
  684.                             WizardNext(hwnd, IDD_PSW_ADDUSER);
  685.                             break;
  686.                         case IDC_WORKGROUP:
  687.                             WizardNext(hwnd, IDD_PSW_WORKGROUP);
  688.                             break;
  689.                         case IDC_NONE:
  690.                             WizardNext(hwnd, IDD_PSW_AUTOLOGON);
  691.                             break;
  692.                     }
  693.                     return TRUE;
  694.                 }
  695.             }
  696.             break;
  697.         }
  698.     }
  699.     return FALSE;
  700. }
  701. /*-----------------------------------------------------------------------------
  702. / Main entry point used to invoke the wizard.
  703. /----------------------------------------------------------------------------*/
  704. static WNDPROC _oldDlgWndProc;
  705. LRESULT CALLBACK _WizardSubWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  706. {
  707.     //
  708.     // on WM_WINDOWPOSCHANGING and the window is moving then lets centre it onto the
  709.     // desktop window.  unfortunately setting the DS_CENTER bit doesn't buy us anything
  710.     // as the wizard is resized after creation.
  711.     //
  712.     if ( uMsg == WM_WINDOWPOSCHANGING )
  713.     {
  714.         LPWINDOWPOS lpwp = (LPWINDOWPOS)lParam;
  715.         RECT rcDlg, rcDesktop;
  716.         GetWindowRect(hwnd, &rcDlg);
  717.         GetWindowRect(GetDesktopWindow(), &rcDesktop);
  718.         lpwp->x = ((rcDesktop.right-rcDesktop.left)-(rcDlg.right-rcDlg.left))/2;
  719.         lpwp->y = ((rcDesktop.bottom-rcDesktop.top)-(rcDlg.bottom-rcDlg.top))/2;
  720.         lpwp->flags &= ~SWP_NOMOVE;
  721.     }
  722.     return _oldDlgWndProc(hwnd, uMsg, wParam, lParam);        
  723. }
  724. int CALLBACK _PropSheetCB(HWND hwnd, UINT uMsg, LPARAM lParam)
  725. {
  726.     switch ( uMsg )
  727.     {
  728.         //
  729.         // in pre-create lets set the window styles accorindlgy
  730.         //      - remove the context menu and system menu
  731.         //
  732.         case PSCB_PRECREATE:
  733.         {
  734.             DLGTEMPLATE *pdlgtmp = (DLGTEMPLATE*)lParam;
  735.             pdlgtmp->style &= ~(DS_CONTEXTHELP|WS_SYSMENU);
  736.             break;
  737.         }
  738.         //
  739.         // we now have a dialog, so lets sub class it so we can stop it being
  740.         // move around.
  741.         //
  742.         case PSCB_INITIALIZED:
  743.         {
  744.             if ( g_uWizardIs != NAW_NETID )
  745.                 _oldDlgWndProc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)_WizardSubWndProc);
  746.             break;
  747.         }
  748.     }
  749.     return FALSE;
  750. }
  751. // The global group page base object used by the domain wizard
  752. // defined in domain.cpp
  753. extern CGroupPageBase* g_pGroupPageBase;
  754. STDAPI NetAccessWizard(HWND hwnd, UINT uType, BOOL *pfReboot)
  755. {
  756.     PROPSHEETHEADER psh = { 0 };
  757.     HPROPSHEETPAGE rghpage[ARRAYSIZE(pages)];
  758.     INT cPages = 0;
  759.     INITCOMMONCONTROLSEX iccex = { 0 };
  760.     iccex.dwSize = sizeof (iccex);
  761.     iccex.dwICC = ICC_LISTVIEW_CLASSES;
  762.     InitCommonControlsEx(&iccex);
  763.     //
  764.     // decode the type and set our state accordingly
  765.     //
  766.     switch ( uType )
  767.     {
  768.         case NAW_NETID:
  769.             break;
  770.         case NAW_PSWORKGROUP:
  771.         case NAW_PSDOMAINJOINFAILED:
  772.             g_dwWhichNet = IDC_NONE;
  773.             g_uWizardIs = uType;
  774.             break;
  775.         case NAW_PSDOMAINJOINED:
  776.             g_dwWhichNet = IDC_DOMAIN;
  777.             g_uWizardIs = uType;
  778.             break;
  779.         default:
  780.             return E_INVALIDARG;
  781.     }
  782.     //
  783.     // build the pages for the wizard.
  784.     //
  785.     for ( cPages = 0 ; cPages < ARRAYSIZE(pages) ; cPages++ )
  786.     {                           
  787.         PROPSHEETPAGE psp = { 0 };
  788.         WCHAR szBuffer[MAX_PATH] = { 0 };
  789.         psp.dwSize = SIZEOF(PROPSHEETPAGE);
  790.         psp.hInstance = GLOBAL_HINSTANCE;
  791.         psp.lParam = cPages;
  792.         psp.dwFlags = PSP_USETITLE | PSP_DEFAULT | PSP_USEHEADERTITLE | 
  793.                             PSP_USEHEADERSUBTITLE | pages[cPages].dwFlags;
  794.         psp.pszTemplate = pages[cPages].idPage;
  795.         psp.pfnDlgProc = pages[cPages].pDlgProc;
  796.         psp.pszTitle = MAKEINTRESOURCE(IDS_NETWIZCAPTION);
  797.         psp.pszHeaderTitle = pages[cPages].pHeading;
  798.         psp.pszHeaderSubTitle = pages[cPages].pSubHeading;
  799.         rghpage[cPages] = CreatePropertySheetPage(&psp);
  800.     }
  801.     //
  802.     // wizard pages are ready, so lets display the wizard.
  803.     //
  804.     psh.dwSize = SIZEOF(PROPSHEETHEADER);
  805.     psh.hwndParent = hwnd;
  806.     psh.hInstance = GLOBAL_HINSTANCE;
  807.     psh.dwFlags = PSH_WIZARD | PSH_WIZARD97 | PSH_WATERMARK | 
  808.                             PSH_STRETCHWATERMARK | PSH_HEADER | PSH_USECALLBACK;
  809.     psh.pszbmHeader = MAKEINTRESOURCE(IDB_PSW_BANNER);
  810.     psh.pszbmWatermark = MAKEINTRESOURCE(IDB_PSW_WATERMARK);
  811.     psh.nPages = cPages;
  812.     psh.phpage = rghpage;
  813.     psh.pfnCallback = _PropSheetCB;
  814.     // Create the global CGroupPageBase object if necessary
  815.     CGroupInfoList grouplist;
  816.     if (SUCCEEDED(grouplist.Initialize()))
  817.     {
  818.         g_pGroupPageBase = new CGroupPageBase(NULL, &grouplist);
  819.         if (NULL != g_pGroupPageBase)
  820.         {
  821.             PropertySheetIcon(&psh, MAKEINTRESOURCE(IDI_PSW));
  822.             delete g_pGroupPageBase;
  823.         }
  824.     }
  825.     //
  826.     // Hang up the all RAS connections if the wizard created one. It is assumed that no non-wizard connections will
  827.     // exist at this time. 90% of the time, they've just changed their domain membership anyway to they will
  828.     // be just about to reboot. Hanging up all connections MAY cause trouble if: There were existing connections
  829.     // before the pre-logon wizard started AND the user cancelled after making connections with the wizard but before
  830.     // changing their domain. There are no situations where this currently happens.
  831.     //
  832.     if (g_fWizardCreatedRASConnection)
  833.     {
  834.         RASCONN* prgrasconn = (RASCONN*) LocalAlloc(0, sizeof(RASCONN));
  835.         if (NULL != prgrasconn)
  836.         {
  837.             prgrasconn[0].dwSize = sizeof(RASCONN);
  838.             DWORD cb = sizeof(RASCONN);
  839.             DWORD nConn = 0;
  840.             DWORD dwSuccess = RasEnumConnections(prgrasconn, &cb, &nConn);
  841.             if (ERROR_BUFFER_TOO_SMALL == dwSuccess)
  842.             {
  843.                 LocalFree(prgrasconn);
  844.                 prgrasconn = (RASCONN*) LocalAlloc(0, cb);
  845.                 if (NULL != prgrasconn)
  846.                 {
  847.                     prgrasconn[0].dwSize = sizeof(RASCONN);
  848.                     dwSuccess = RasEnumConnections(prgrasconn, &cb, &nConn);
  849.                 }
  850.             }
  851.             if (0 == dwSuccess)
  852.             {
  853.                 // Make sure we have one and only one connection before hanging up
  854.                 for (DWORD i = 0; i < nConn; i ++)
  855.                 {
  856.                     RasHangUp(prgrasconn[i].hrasconn);
  857.                 }
  858.             }
  859.             LocalFree(prgrasconn);
  860.         }
  861.     }
  862.     //
  863.     // restart the machine if we need to, eg: the domain changed
  864.     //
  865.     if ( pfReboot )
  866.         *pfReboot = g_fRebootOnExit;
  867.     //
  868.     // if this is coming from setup, then lets display the message
  869.     //
  870.     if ( g_fRebootOnExit && !g_fShownLastPage && (g_uWizardIs != NAW_NETID) )
  871.     {
  872.         ShellMessageBox(GLOBAL_HINSTANCE, 
  873.                         hwnd,
  874.                         MAKEINTRESOURCE(IDS_RESTARTREQUIRED), MAKEINTRESOURCE(IDS_NETWIZCAPTION),
  875.                         MB_OK);        
  876.     }
  877.     
  878.     return S_OK;
  879. }
  880. void APIENTRY NetAccWizRunDll(HWND hwndStub, HINSTANCE hAppInstance, LPSTR pszCmdLine, int nCmdShow)
  881. {
  882.     UINT uType = 0;
  883.     if ( *pszCmdLine )
  884.         uType = StrToIntA(pszCmdLine);
  885.     NetAccessWizard(hwndStub, uType, NULL);
  886. }