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

Windows Kernel

Development Platform:

Visual C++

  1. #include "priv.h"
  2. #include "srvwiz.h"
  3. #include <dsrole.h>
  4. #include <clusapi.h>
  5. #include <winsvc.h>
  6. #include "dspsprt.h"
  7. #include "resource.h"
  8. #define SZ_REGKEY_NTCV              TEXT("SOFTWARE\Microsoft\Windows NT\CurrentVersion")
  9. #define SZ_REGKEY_SRVWIZ            TEXT("SOFTWARE\Microsoft\Windows NT\CurrentVersion\SrvWiz")
  10. #define SZ_REGKEY_TODOLIST          TEXT("SOFTWARE\Microsoft\Windows NT\CurrentVersion\Setup\OCManager\ToDoList")
  11. #define SZ_REGKEY_WELCOME           TEXT("SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Tips")
  12. #define SZ_REGKEY_MSMQ              TEXT("SOFTWARE\Microsoft\MSMQ\Parameters")
  13. #define SZ_REGKEY_RRAS              TEXT("System\CurrentControlSet\Services\RemoteAccess")
  14. #define SZ_REGKEY_NETSHOW           TEXT("SOFTWARE\Microsoft\NetShow")
  15. //
  16. // HOME_STATE decides the first page to show at start up
  17. //
  18. typedef enum _HOME_STATE {
  19.     HOME_FINISH     = 0x00000000,   // finish OC setup
  20.     HOME_INTRO1,                    // server choice page
  21.     HOME_INTRO2,
  22.     HOME_DETAILS,
  23.     HOME_INTRO3,
  24.     HOME_NEXT,
  25.     HOME_TMP,                       // my first server middle state 
  26.     HOME_CONFIG,                    // either the machine is a DC, or has run through my first server steps
  27.     HOME_MULTISERVER                // user selected multiple server in intro1.htm
  28. } HOME_STATE;
  29. // utility functions declaration
  30. BOOL ValidateDomainDNSName(LPWSTR pszDomainDNSName);
  31. BOOL ValidateDomainNetBiosName(LPWSTR pszDomainNetBiosName);
  32. BOOL IsTerminalServicesRunning(void);
  33. BOOL VerifyClusterOS(void);
  34. BOOL IsTerminalServicesInstalled(void);
  35. LPTSTR WINAPI MyFormatString(UINT resId, ...);
  36. LPSTR WINAPI MyFormatStringAnsi(UINT resId, ...);
  37. HRESULT CreateTempFile(LPCTSTR szPath, LPSTR szText);
  38. BOOL InstallDNS(BOOL bWait);
  39. BOOL InstallDHCP(BOOL bWait);
  40. BOOL InstallAD(BOOL bWait);
  41. VOID SetStaticIPAddressAndSubnetMask();
  42. EXTERN_C void RegisterWLNotifyEvent(void);
  43. EXTERN_C BOOL IsDhcpServerAround(VOID);
  44. class CSrvWiz : public ISrvWiz
  45.               , public CImpIDispatch
  46. {
  47. public:
  48.     // *** IUnknown Methods
  49.     STDMETHOD(QueryInterface)(REFIID riid, LPVOID * ppvObj);
  50.     STDMETHOD_(ULONG, AddRef)(void) ;
  51.     STDMETHOD_(ULONG, Release)(void);
  52.     // *** IDispatch methods ***
  53.     STDMETHOD(GetTypeInfoCount)(UINT * pctinfo);
  54.     STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo * * pptinfo);
  55.     STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR * * rgszNames, UINT cNames, LCID lcid, DISPID * rgdispid);
  56.     STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr);
  57.     // *** ISrvWiz
  58.     STDMETHOD(get_Home)(/*[out, retval]*/ DWORD *pdwHome);
  59.     STDMETHOD(put_Home)(/*[in]*/ DWORD dwHome);
  60.     STDMETHOD(get_ShowAtStartup)(/*[out, retval]*/ BOOL *pbShow);
  61.     STDMETHOD(put_ShowAtStartup)(/*[in]*/ BOOL bShow);
  62.     STDMETHOD(put_DomainDNSName)(/*[in]*/ BSTR bstrName);
  63.     STDMETHOD(put_DomainNetBiosName)(/*[in]*/ BSTR bstrName);
  64.     STDMETHOD(get_ProductRegistered)(/*[out, retval]*/ BOOL *pbRet);
  65.     STDMETHOD(DsRole)(/*[in*/ DWORD dwInfoLevel, /*[out, retval]*/ DWORD *pdwRole);
  66.     
  67.     STDMETHOD(ServiceState)(/*[in]*/ BSTR bstrService, /*[out, retval]*/ DWORD *pdwState);
  68.     STDMETHOD(InstallService)(/*[in]*/ BSTR bstrService, /*[out, retval]*/ BOOL *pbRet);
  69.     STDMETHOD(ValidateName)(/*[in]*/ BSTR bstrType, /*[in]*/ BSTR bstrName, /*[out, retval]*/ BOOL *pbRet);
  70.     STDMETHOD(SetupFirstServer)(/*[out, retval]*/ BOOL *pbRet);
  71.     STDMETHOD(CheckDHCPServer)(/*[out, retval]*/ BOOL *pbRet);
  72.     CSrvWiz();
  73.     ~CSrvWiz();
  74.     // friend function
  75.     friend HRESULT CSrvWiz_CreateInstance(REFIID riid, void **ppvObj);
  76. private:
  77.     UINT _cRef;
  78. } ;
  79. // constructor
  80. CSrvWiz::CSrvWiz() : CImpIDispatch(&LIBID_SrvWizLib, 1, 0, &IID_ISrvWiz)
  81. {
  82.     _cRef = 1;
  83.     DllAddRef();
  84. }
  85. // destructor
  86. CSrvWiz::~CSrvWiz()
  87. {
  88.     DllRelease();
  89. }
  90. // ISrvWiz::QueryInterface
  91. HRESULT CSrvWiz::QueryInterface(REFIID riid, LPVOID * ppvOut)
  92. {
  93.     if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ISrvWiz))
  94.     {
  95.         *ppvOut = SAFECAST(this, ISrvWiz *);
  96.     }
  97.     else if (IsEqualIID(riid, IID_IDispatch))
  98.     {
  99.         *ppvOut = SAFECAST(this, IDispatch *);
  100.     }
  101.     else
  102.     {
  103.         *ppvOut = NULL;
  104.         return E_NOINTERFACE;
  105.     }
  106.     AddRef();
  107.     return S_OK;
  108. }
  109. // ISrvWiz::AddRef
  110. ULONG CSrvWiz::AddRef()
  111. {
  112.     _cRef++;
  113.     return _cRef;
  114. }
  115. // ISrvWiz::Release
  116. ULONG CSrvWiz::Release()
  117. {
  118.     _cRef--;
  119.     if (_cRef > 0)
  120.         return _cRef;
  121.     delete this;
  122.     return 0;
  123. }
  124. //
  125. // CSrvWiz IDispatch implementation
  126. //
  127. STDMETHODIMP CSrvWiz::GetTypeInfoCount(UINT * pctinfo)
  128.     return CImpIDispatch::GetTypeInfoCount(pctinfo); 
  129. }
  130. STDMETHODIMP CSrvWiz::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo ** pptinfo)
  131.     return CImpIDispatch::GetTypeInfo(itinfo, lcid, pptinfo); 
  132. }
  133. STDMETHODIMP CSrvWiz::GetIDsOfNames(REFIID riid, OLECHAR ** rgszNames, UINT cNames, LCID lcid, DISPID * rgdispid)
  134.     return CImpIDispatch::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  135. }
  136. STDMETHODIMP CSrvWiz::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr)
  137. {
  138.     return CImpIDispatch::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
  139. }
  140. //
  141. // CSrvWiz ISrvWiz implementation
  142. //
  143. STDMETHODIMP CSrvWiz::get_Home(DWORD *pdwHome)
  144. {
  145.     HKEY hkey;
  146.     DWORD cSubKeys = 0; // number of subkeys under ToDoList
  147.     if (!pdwHome)
  148.         return E_INVALIDARG;
  149.     
  150.     // Check ToDoList first. If there is anything under it, show finish.htm to finish setup
  151.     if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, SZ_REGKEY_TODOLIST, &hkey))
  152.     {
  153.         RegQueryInfoKey(hkey, NULL, NULL, NULL, &cSubKeys, NULL, 
  154.                         NULL, NULL, NULL, NULL, NULL, NULL
  155.                        );
  156.         RegCloseKey(hkey);
  157.     }
  158.     if (cSubKeys)
  159.     {
  160.         *pdwHome = HOME_FINISH;
  161.     }
  162.     else 
  163.     {
  164.         // Then check whether this machine is a DC. If so, go directly to config.htm
  165.         DWORD dwDsRole = 0;
  166.         DsRole(0, &dwDsRole);
  167.         if (dwDsRole)
  168.         {
  169.             // remember state in registry
  170.             DWORD cbSize = sizeof(*pdwHome);
  171.             DWORD dwRet = SHGetValue(HKEY_LOCAL_MACHINE, SZ_REGKEY_SRVWIZ, TEXT("home"), 
  172.                                      NULL, (LPVOID)pdwHome, &cbSize);
  173.             if ((NO_ERROR != dwRet) || (HOME_CONFIG != *pdwHome))
  174.             {
  175.                 put_Home(HOME_CONFIG);
  176.             }
  177.             *pdwHome = HOME_CONFIG;
  178.         }
  179.         else
  180.         {
  181.             // Last, check registry for state in My First Server steps
  182.             DWORD cbSize = sizeof(*pdwHome);
  183.             DWORD dwRet = SHGetValue(HKEY_LOCAL_MACHINE, SZ_REGKEY_SRVWIZ, TEXT("home"), 
  184.                                      NULL, (LPVOID)pdwHome, &cbSize
  185.                                     );
  186.             if ((NO_ERROR != dwRet) ||          // First time run CYS
  187.                 (HOME_MULTISERVER < *pdwHome) || (HOME_FINISH > *pdwHome) ||    // corrupted registry
  188.                 (HOME_CONFIG == *pdwHome) ||    // the machine is no longer a DC
  189.                 (HOME_TMP == *pdwHome )         // my first server setup failed
  190.                )
  191.             {
  192.                 *pdwHome = HOME_INTRO1;
  193.                 put_Home(HOME_INTRO1);  // repair registry and start My First Server steps
  194.             }
  195.         }
  196.     }
  197.     return S_OK;
  198. }
  199. STDMETHODIMP CSrvWiz::put_Home(DWORD dwHome)
  200. {
  201.     if ((HOME_MULTISERVER < dwHome) || (HOME_FINISH > dwHome))
  202.         return E_INVALIDARG;
  203.     SHSetValue(HKEY_LOCAL_MACHINE, SZ_REGKEY_SRVWIZ, TEXT("home"), 
  204.                REG_DWORD, (LPVOID)&dwHome, sizeof(dwHome));
  205.     return S_OK;
  206. }
  207. STDMETHODIMP CSrvWiz::get_ShowAtStartup(BOOL *pbShow)
  208. {
  209.     DWORD dwShow;
  210.     DWORD cbShow = sizeof(dwShow);
  211.     if (!pbShow)
  212.         return E_INVALIDARG;
  213.     *pbShow = TRUE; // always show it by default
  214.     if (NO_ERROR == SHGetValue(HKEY_CURRENT_USER, SZ_REGKEY_WELCOME, TEXT("show"), 
  215.                                NULL, &dwShow, &cbShow)
  216.        )
  217.     {
  218.         *pbShow = (dwShow != 0);
  219.     }
  220.     return S_OK;
  221. }
  222. STDMETHODIMP CSrvWiz::put_ShowAtStartup(BOOL bShow)
  223. {
  224.     DWORD dwShow = bShow ? 1 : 0;
  225.     
  226.     SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_WELCOME, TEXT("show"), 
  227.                REG_DWORD, (LPVOID)&dwShow, sizeof(dwShow));
  228.     return S_OK;
  229. }
  230. STDMETHODIMP CSrvWiz::put_DomainDNSName(BSTR bstrDomainDNSName)
  231. {
  232.     if (NULL == bstrDomainDNSName || !*bstrDomainDNSName)
  233.         return E_INVALIDARG;
  234.     SHSetValueW(HKEY_LOCAL_MACHINE, SZ_REGKEY_SRVWIZ, L"DomainDNSName", 
  235.                 REG_SZ, bstrDomainDNSName, 
  236.                 (lstrlenW(bstrDomainDNSName)+1)*sizeof(WCHAR));
  237.     return S_OK;
  238. }
  239. STDMETHODIMP CSrvWiz::put_DomainNetBiosName(BSTR bstrDomainNetBiosName)
  240. {
  241.     if (NULL == bstrDomainNetBiosName || !*bstrDomainNetBiosName)
  242.         return E_INVALIDARG;
  243.     SHSetValueW(HKEY_LOCAL_MACHINE, SZ_REGKEY_SRVWIZ, L"DomainNetBiosName", 
  244.                 REG_SZ, bstrDomainNetBiosName, 
  245.                 (lstrlenW(bstrDomainNetBiosName)+1)*sizeof(WCHAR));
  246.     return S_OK;
  247. }
  248. STDMETHODIMP CSrvWiz::get_ProductRegistered(BOOL *pbReg)
  249. {
  250.     TCHAR szData[16];
  251.     DWORD cbSize = sizeof(szData);
  252.     DWORD dwRet;
  253.     if (!pbReg)
  254.         return E_INVALIDARG;
  255.     *pbReg = FALSE; // Assume it is not registered
  256.     
  257.     dwRet = SHGetValue(HKEY_LOCAL_MACHINE, SZ_REGKEY_NTCV, TEXT("Regdone"), 
  258.                        NULL, (LPVOID)szData, &cbSize);
  259.     if ((NO_ERROR == dwRet) && !StrCmpI(TEXT("1"), szData))
  260.         *pbReg = TRUE;
  261.     return S_OK;
  262. }
  263. STDMETHODIMP CSrvWiz::DsRole(DWORD dwInfoLevel, DWORD *pdwRole)
  264. {
  265.     DWORD dwRet;
  266.     // parameter checking
  267.     if (!pdwRole )
  268.     {
  269.         return E_INVALIDARG;
  270.     }
  271.     // by default, assume the machine is not a DC, and not in the middle of upgrade
  272.     *pdwRole = 0;
  273.     if (dwInfoLevel == 0)
  274.     {
  275.         // check whetehr this machine is a DC
  276.         
  277.         PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pdib = NULL;
  278.         dwRet = DsRoleGetPrimaryDomainInformation(
  279.                     NULL, 
  280.                     DsRolePrimaryDomainInfoBasic, 
  281.                     (PBYTE *)&pdib
  282.                     );
  283.                     
  284.         if ((ERROR_SUCCESS == dwRet) && pdib)
  285.         {
  286.             if ((DsRole_RoleBackupDomainController == pdib->MachineRole) ||
  287.                 (DsRole_RolePrimaryDomainController == pdib->MachineRole)
  288.                )
  289.             {
  290.                 *pdwRole = 1;   // this is a DC
  291.             }
  292.             else
  293.             {
  294.                 *pdwRole = 0;   // this is not a DC
  295.             }
  296.             
  297.             DsRoleFreeMemory(pdib);
  298.         }
  299.     } 
  300.     else if (dwInfoLevel == 1)
  301.     {
  302.         // check whether this machine is in the middle of upgrade
  303.         
  304.         PDSROLE_UPGRADE_STATUS_INFO pusi = NULL;
  305.         dwRet = DsRoleGetPrimaryDomainInformation(
  306.                     NULL, 
  307.                     DsRoleUpgradeStatus,
  308.                     (PBYTE *)&pusi
  309.                     );
  310.                     
  311.         if ((ERROR_SUCCESS == dwRet) && pusi)
  312.         {
  313.             if (DSROLE_UPGRADE_IN_PROGRESS == pusi->OperationState)
  314.             {
  315.                 *pdwRole = 1;
  316.             }
  317.             
  318.             DsRoleFreeMemory(pusi);
  319.         }
  320.     }
  321.     return S_OK;
  322. }
  323. // For most services:
  324. //     return -1 if the service should not be installed, 
  325. //     return 0 if not installed, 
  326. //     return 1 if installed
  327. // For others that have more states, it is up to the caller to interprete the return value
  328. STDMETHODIMP CSrvWiz::ServiceState(BSTR bstrService, DWORD *pdwState)
  329. {
  330.     if (!bstrService || !pdwState)
  331.         return E_INVALIDARG;
  332.     *pdwState = 0;
  333.     if (!StrCmpIW(bstrService, L"TerminalServices"))
  334.     {
  335.         if (IsTerminalServicesRunning())
  336.             *pdwState = 1;
  337.     }
  338.     else if (!StrCmpIW(bstrService, L"MessageQueue"))
  339.     {
  340.         // If reg value [HKLMSoftwareMicrosoftMSMQParameters,MaxSysQueue] exists,
  341.         // we assume Message Queue is installed.
  342.         
  343.         DWORD dwRet;
  344.         DWORD dwMaxSysQueue;
  345.         DWORD cbSize = sizeof(dwMaxSysQueue);
  346.         dwRet = SHGetValue(HKEY_LOCAL_MACHINE, SZ_REGKEY_MSMQ, TEXT("MaxSysQueue"), 
  347.                            NULL, (LPVOID)&dwMaxSysQueue, &cbSize);
  348.         if (NO_ERROR == dwRet)
  349.         {
  350.             *pdwState = 1;
  351.         }
  352.     }
  353.     else if (!StrCmpIW(bstrService, L"RemoteAccess") || 
  354.              !StrCmpIW(bstrService, L"Routing"))
  355.     {   
  356.         // If [HKLMSystemCurrentControlSetServicesRemoteAccess, ConfigurationFlags(REG_DWORD)] == 1, 
  357.         // Ras and Routing is configured. RRAS(Routing & Remote Access) is always installed.
  358.         DWORD dwRet;
  359.         DWORD dwCfgFlags;
  360.         DWORD cbSize = sizeof(dwCfgFlags);
  361.         dwRet = SHGetValue(HKEY_LOCAL_MACHINE, SZ_REGKEY_RRAS, TEXT("ConfigurationFlags"), 
  362.                            NULL, (LPVOID)&dwCfgFlags, &cbSize);
  363.         if ((NO_ERROR == dwRet) && (1 == dwCfgFlags))
  364.         {
  365.             *pdwState = 1;
  366.         }
  367.     } 
  368.     else if (!StrCmpIW(bstrService, L"Clustering"))
  369.     {   
  370.         /* 
  371.           publicsdkincclusapi.h:
  372.           #define CLUSTER_INSTALLED   0x00000001
  373.           #define CLUSTER_CONFIGURED  0x00000002
  374.           #define CLUSTER_RUNNING     0x00000010
  375.           typedef enum NODE_CLUSTER_STATE {
  376.           ClusterStateNotInstalled                = 0x00000000,
  377.           ClusterStateNotConfigured               = CLUSTER_INSTALLED,
  378.           ClusterStateNotRunning                  = CLUSTER_INSTALLED | CLUSTER_CONFIGURED,
  379.           ClusterStateRunning                     = CLUSTER_INSTALLED | CLUSTER_CONFIGURED | CLUSTER_RUNNING
  380.           } NODE_CLUSTER_STATE;
  381.         */
  382.         if (VerifyClusterOS() && !IsTerminalServicesInstalled())
  383.         {
  384.             GetNodeClusterState(NULL, pdwState);
  385.         }
  386.         else
  387.         {
  388.             // Clustering services should not be available on this platform.
  389.             *pdwState = -1;
  390.         }
  391.     } 
  392.     else if (!StrCmpIW(bstrService, L"NetShow"))
  393.     {   
  394.         // If we can find nsadmin.exe, we assume netshow is installed
  395.         DWORD dwRet;
  396.         TCHAR szPath[MAX_PATH];
  397.         DWORD cbSize = sizeof(szPath);
  398.         dwRet = SHGetValue(HKEY_LOCAL_MACHINE, SZ_REGKEY_NETSHOW, TEXT("InstallDir"), 
  399.                            NULL, (LPVOID)szPath, &cbSize);
  400.         if ((NO_ERROR == dwRet) && *szPath)
  401.         {
  402.             if (PathAppend(szPath, TEXT("Server\nsadmin.exe")) && PathFileExists(szPath))
  403.             {
  404.                 *pdwState = 1;
  405.             }
  406.         }
  407.     } 
  408.     else
  409.     {
  410.         // For all other services, if we can open the service, we assume it is installed
  411.         SC_HANDLE hsc = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, GENERIC_READ);
  412.         if (hsc)
  413.         {
  414.             SC_HANDLE hs = OpenServiceW(hsc, bstrService, GENERIC_READ);
  415.             if (hs)
  416.             {
  417.                 CloseServiceHandle(hs);
  418.                 *pdwState = 1;
  419.             }
  420.             CloseServiceHandle(hsc);
  421.         }
  422.     }
  423.     return S_OK;
  424. }
  425. // BUGBUG: we can't wait for sysocmgr or dcpromo to finish
  426. // and then check its return value for sucess because it
  427. // can cause system reboot, so here we blindly assume success.
  428. STDMETHODIMP CSrvWiz::InstallService(BSTR bstrService, BOOL *pbRet)
  429. {
  430.     if (!bstrService)
  431.         return E_INVALIDARG;
  432.     if (!StrCmpIW(bstrService, L"DNS"))
  433.     {
  434.         *pbRet = InstallDNS(FALSE);
  435.     }
  436.     else if (!StrCmpIW(bstrService, L"DHCPServer"))
  437.     {
  438.         *pbRet = InstallDHCP(FALSE);
  439.     }
  440.     else if (!StrCmpIW(bstrService, L"AD"))
  441.     {
  442.         *pbRet = InstallAD(FALSE);
  443.     }
  444.     else
  445.         return E_INVALIDARG;
  446.     return S_OK;
  447. }
  448. STDMETHODIMP CSrvWiz::ValidateName(BSTR bstrType, BSTR bstrName, BOOL *pbRet)
  449. {
  450.     HRESULT hr = S_OK;
  451.     
  452.     if (!bstrType || !bstrName || !pbRet)
  453.         return E_INVALIDARG;
  454.     // this is a lengthy operation
  455.     HCURSOR hcurOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
  456.     
  457.     if (!StrCmpIW(bstrType, L"DNS"))
  458.     {
  459.         *pbRet = ValidateDomainDNSName(bstrName);
  460.     }
  461.     else if (!StrCmpIW(bstrType, L"NetBios"))
  462.     {
  463.         *pbRet = ValidateDomainNetBiosName(bstrName);
  464.     }
  465.     else
  466.     {
  467.         *pbRet = FALSE;
  468.         hr = E_INVALIDARG;
  469.     }
  470.     SetCursor(hcurOld);
  471.     
  472.     return hr;
  473. }
  474. // BUGBUG: We can't wait for sysocmgr or dcpromo to finish
  475. // and check the return value because it can cause a reboot.
  476. // So here we register winlogon notify event first, 
  477. // launch both sysocmgr and dcpromo without wait and 
  478. // blindly assume success.
  479. STDMETHODIMP CSrvWiz::SetupFirstServer(BOOL *pbRet)
  480. {
  481.     if (!pbRet)
  482.         return E_INVALIDARG;
  483.     *pbRet = TRUE;  // assume success
  484.     SetStaticIPAddressAndSubnetMask();
  485.     RegisterWLNotifyEvent();
  486.     
  487.     if (!InstallDHCP(TRUE))
  488.     {
  489.         goto Quit;
  490.     }
  491.         
  492.     if (!InstallAD(FALSE))
  493.     {
  494.         goto Quit;
  495.     }
  496.     
  497.     put_Home(HOME_TMP);
  498.     return S_OK;
  499. Quit:
  500.     *pbRet = FALSE;
  501.     return S_OK;
  502. }
  503. STDMETHODIMP CSrvWiz::CheckDHCPServer(BOOL *pbRet)
  504. {
  505.     WSADATA WsaData;
  506.     DWORD Error;
  507.     if (!pbRet)
  508.         return E_INVALIDARG;
  509.     *pbRet = TRUE;
  510.     
  511.     Error = WSAStartup(MAKEWORD(2,0), &WsaData );
  512.     if( NO_ERROR == Error )
  513.     {
  514.         if( !IsDhcpServerAround() )
  515.             *pbRet = FALSE;
  516.         WSACleanup();
  517.     }
  518.     
  519.     return S_OK;
  520. }
  521. /*----------------------------------------------------------
  522. Purpose: Create-instance function for class factory
  523. */
  524. HRESULT CSrvWiz_CreateInstance(REFIID riid, LPVOID * ppvObj)
  525. {
  526.     // aggregation checking is handled in class factory
  527.     HRESULT hres = E_OUTOFMEMORY;
  528.     CSrvWiz* pObj = new CSrvWiz();
  529.     if (pObj)
  530.     {
  531.         hres = pObj->QueryInterface(riid, ppvObj);
  532.         pObj->Release();
  533.     }
  534.     return hres;
  535. }