text: // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  
  // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  
  // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  
  // PARTICULAR PURPOSE.
  
  //
  
  // Copyright (c) Microsoft Corporation. All rights reserved.
  
  #include "precomp.h"
  #include "resource.h"
  #include "shvui.h"
  #include "shvuicf.h"
  #include "regutil.h"
  
  SHVUIClassFactoryData* g_FactoryData = NULL;
  HWND g_hwndDlg = NULL;
  HINSTANCE g_hInst = NULL;
  
  // Cache of the remote configuration 
  // or non-default configuration (multi-config)
  BYTE g_config = 0;
  
  //
  // g_fConfigModeMemoryOnly indicates that we are on remote configuration 
  // or non-default configuration (multi-config).
  // Hence instead of reading the configuration settings from registry, read it 
  // from g_config, which a cache of the configuration result, 
  // and the caller (NPS UI) will call SetConfig() or SetConfigToID() to persist it. 
  
  // When configuring the remote machine, the local machine invokes 
  // INapComponentConfig::GetConfig() on remote machine to obtain the remote 
  // machine configuration, it then invokes local UI by calling 
  // INapComponentConfig2::InvokeUIFromConfigBlob() and obtains user's changes. 
  // It sets the new changes to remote machine using 
  // INapComponentConfig::SetConfig().
  //
  
  // When configuring a multi-config configuration, the scenario is similar to 
  // the remote configuration. The only difference is that
  // INapComponentConfig::GetConfig() is replaced with INapComponentConfig3::GetConfigFromID() 
  // and INapComponentConfig::SetConfig() is replaced with INapComponentConfig3::SetConfigToID()
  //
  BOOL g_fConfigModeMemoryOnly = FALSE;
  
  INT_PTR CALLBACK DlgProcSHVPage(
               HWND hDlg, 
               UINT message, 
               WPARAM wParam, 
               LPARAM //lParam
               );
  
  // Caller needs to pass in an array of size of MAX_PATH or bigger to use this function safely.
  void AssembleRegkeyPathWithID (__out_ecount(MAX_PATH) LPTSTR pwszConfigRegkeyWithID, __in UINT32 uConfigID);
  
  int __stdcall wWinMain(
      __in HINSTANCE hInst, 
      __in_opt HINSTANCE, // unreferenced hPrevInst
      __in_opt LPWSTR lpCmdLine, 
      __in int // unreferenced nCmdShow
      ) 
  {
      BOOL bExit = FALSE ;
      BOOL bShow = TRUE;
      BOOL bCOMInvoked = FALSE;
  
      int bRetCode = TRUE;
      BOOL bIsCOMInitialized = FALSE;
  
      WCHAR wszCmd[64];
      int nMax = sizeof(wszCmd)/sizeof(WCHAR);
      
  
      g_hInst = hInst;
  
      g_FactoryData = new SHVUIClassFactoryData();
      if (g_FactoryData == NULL)
      {
          return FALSE;
      }
  
  
      HRESULT hr = CoInitialize(NULL) ;
      if (FAILED(hr))
      {
          bRetCode = FALSE;
          goto Cleanup;
      }
  
      bIsCOMInitialized = TRUE;
  
      // Check for "/RegServer" or "/UnRegServer" parameters.
      LPWSTR szTokens = L"-/" ;
  	LPWSTR szNextToken = NULL;
      LPWSTR szToken = wcstok_s(lpCmdLine, szTokens, &szNextToken) ; 
      while (szToken != NULL)
      {
          LoadString(hInst, IDS_CMD_EMBEDDED, wszCmd, nMax);
          if (_wcsicmp(szToken, wszCmd) == 0)
          {
              //Called through INapComponentConfig.  Hide until InvokeUI() call.
              bCOMInvoked = TRUE;
              bShow = FALSE;
          }
          LoadString(hInst, IDS_CMD_UNREGSERVER, wszCmd, nMax);
          if (_wcsicmp(szToken, wszCmd) == 0)
          {
              ShvUIClassFactory::Unregister() ;
              // We are done, so exit.
              bExit = TRUE ;
          }
          LoadString(hInst, IDS_CMD_REGSERVER, wszCmd, nMax);
          if (_wcsicmp(szToken, wszCmd) == 0)
          {
              ShvUIClassFactory::Register() ;
              // We are done, so exit.
              bExit = TRUE ;
          }
  
          szToken = wcstok_s(NULL, szTokens, &szNextToken) ;
      }
  
      if (bExit)
      {
          goto Cleanup;
      }
  
      ShvUIClassFactory::StartFactory();
  
      if (bCOMInvoked)
      {
          //Process / dispatch messages, allow system to wait for COM method calls
          BOOL bContinue = TRUE;
          DWORD dwResult;
          while (bContinue)
          {
              dwResult = MsgWaitForMultipleObjects (
                                  1,
                                  NULL,
                                  FALSE,
                                  INFINITE,
                                  QS_ALLINPUT);
              switch (dwResult)
              {
                  case WAIT_OBJECT_0 + 1:
                      MSG msg;
                      while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
                      {
                          if (msg.message == WM_QUIT)
                          {
                              bContinue = FALSE;
                              PostQuitMessage(0);
                              break;
                          }
                          else
                          {
                              TranslateMessage(&msg);
                              DispatchMessage(&msg);
                          }
                      }
                      break;
  
                  default:
                      break;
              }
          }
  
      }
  
  Cleanup:
  
      ShvUIClassFactory::StopFactory();
  
      if (bIsCOMInitialized)
      {
          CoUninitialize();
      }
  
      if (g_FactoryData != NULL)
      {
          delete (g_FactoryData);
          g_FactoryData = NULL;
      }
  
      return bRetCode ;
  }
  
  ShvUI::~ShvUI()
  {
      //The only supported interface is destroyed...quit the application
      PostQuitMessage(0);
  }
  
  
  //Implementation of INapComponentConfig
  STDMETHODIMP ShvUI::QueryInterface(const IID& iid, void** ppv)
  {
      if (iid == IID_IUnknown)
      {
          *ppv = static_cast<INapComponentConfig*>(this);
      }
      else if (iid == IID_INapComponentConfig)
      {
          *ppv = static_cast<INapComponentConfig*>(this);
      }
      else if (iid == IID_INapComponentConfig2)
      {
          *ppv = static_cast<INapComponentConfig2*>(this);
      }
      else if (iid == IID_INapComponentConfig3)
      {
          *ppv = static_cast<INapComponentConfig3*>(this);
      }
      else
      {
          *ppv = NULL;
          return E_NOINTERFACE;
      }
      reinterpret_cast<IUnknown*>(*ppv)->AddRef();
      return S_OK;
  }
  
  ULONG ShvUI::AddRef()
  {
      return InterlockedIncrement(&m_cRef);
  }
  
  ULONG ShvUI::Release()
  {
  
      ULONG cRef = InterlockedDecrement(&m_cRef);
      if (cRef == 0)
      {
          delete this;
      }
      return cRef;
  }
  
  
  STDMETHODIMP ShvUI::IsUISupported(BOOL* isSupported)
  {
      *isSupported = TRUE;
      return S_OK;
  }
  
  STDMETHODIMP ShvUI::InvokeUI(HWND hwndParent)
  {
      DialogBox(
        g_hInst, 
        MAKEINTRESOURCE(IDD_SDKSHV_DIALOG),
        hwndParent,
        DlgProcSHVPage
        );
  
      return S_OK;
  }
  
  
  STDMETHODIMP
  ShvUI::GetConfig(UINT16 *bCount, BYTE** data)
  {
      if (!bCount || !data)
      {
          return E_INVALIDARG;
      }
  
      DWORD result = ERROR_SUCCESS;
      DWORD dwIsChecked = TRUE;
  
      result = ShvuiGetRegistryValue(
                       HKEY_LOCAL_MACHINE,
                       SDKSHV_DEFAULT_CONFIG_KEY,
                       SHV_CONFIG_BLOB,
                       REG_DWORD,
                       (PVOID*)&dwIsChecked
                       );
  
      *bCount = (UINT16) sizeof(BYTE);
      *data = (BYTE*) CoTaskMemAlloc(sizeof(BYTE));
      if (*data)
      {
          **data = (BYTE) dwIsChecked;
      }
  
      return result;
  }
  
  
  
  STDMETHODIMP
  ShvUI::SetConfig(UINT16 bCount, BYTE* data)
  {
      if (!data)
      {
          return E_INVALIDARG;
      }
  
      if (bCount == sizeof(g_config))
      {
          // set the cached data
          g_config = *data; 
  
          // commit the cache
          BOOL isChecked = g_config;
          ShvuiSetRegistryValue(
                          SDKSHV_DEFAULT_CONFIG_KEY,
                          NULL,
                          SHV_CONFIG_BLOB,
                          REG_DWORD,
                          (PBYTE)&isChecked,
                          sizeof(DWORD)
                          );
      }
      return S_OK;
  }
  
  STDMETHODIMP 
  ShvUI::IsRemoteConfigSupported(BOOL* isSupported, UINT8* remoteConfigType)
  {
      *isSupported = TRUE;
      *remoteConfigType = remoteConfigTypeConfigBlob;
      return S_OK;
  }
  
  STDMETHODIMP 
  ShvUI::InvokeUIForMachine(HWND hwndParent, CountedString* machineName)
  {
      MessageBox(hwndParent, L"InvokeUIForMachine", machineName->string, MB_OK);
      return S_OK;
  }
  
  STDMETHODIMP 
  ShvUI::InvokeUIFromConfigBlob(
                                  HWND hwndParent,
                                  UINT16 inbCount,
                                  BYTE* inData, 
                                  UINT16* outbCount, 
                                  BYTE** outdata, 
                                  BOOL *fConfigChanged
                                        )
  {
      if (inbCount != sizeof(g_config))
      {
           return E_INVALIDARG;
      }
  
      g_fConfigModeMemoryOnly = TRUE;
  
      // 
      // We should have set it TRUE only if the results before and after are different.
      // To keep it simple, set it TRUE without comparison.
      //
      *fConfigChanged = TRUE;
  
      g_config = *inData;
  
      DialogBox(
        g_hInst, 
        MAKEINTRESOURCE(IDD_SDKSHV_DIALOG),
        hwndParent,
        DlgProcSHVPage
        );
  
      *outbCount = (UINT16) inbCount;
      *outdata = (BYTE*)CoTaskMemAlloc(*outbCount);
      **outdata = g_config;
  
      g_fConfigModeMemoryOnly = FALSE;
      return S_OK;
  }
  
  
  // *********************************************************************
  // INapComponentConfig3 methods:
  // *********************************************************************
  
  STDMETHODIMP ShvUI::NewConfig(UINT32 configID)
  {
      // We have no action to take, and we act when SetConfigToID is called.
      UNREFERENCED_PARAMETER(configID);
      return S_OK;
  }
  
  STDMETHODIMP ShvUI::DeleteConfig(UINT32 configID)
  {
      WCHAR wszConfigRegkeyWithID[MAX_PATH] = {0};
      AssembleRegkeyPathWithID(wszConfigRegkeyWithID, configID);
      ShvuiDeleteRegistryKey(wszConfigRegkeyWithID);
      return S_OK;
  }
  
  STDMETHODIMP ShvUI::DeleteAllConfig()
  {
      ShvuiDeleteRegistryKey(SDKSHV_MULTI_CONFIG_KEY);
      return S_OK;
  }
  
  STDMETHODIMP ShvUI::GetConfigFromID(UINT32 configID, UINT16* bCount, BYTE** outdata)
  {
      if (!bCount || !outdata)
      {
          return E_INVALIDARG;
      }
  
      if (configID == DEFAULT_CONFIGURATION_ID)
      {
          return GetConfig(bCount, outdata);
      }
  
      DWORD result = ERROR_SUCCESS;
      DWORD dwIsChecked = TRUE;
  
      WCHAR wszConfigRegkeyWithID[MAX_PATH] = {0};
      AssembleRegkeyPathWithID(wszConfigRegkeyWithID, configID);
  
      result = ShvuiGetRegistryValue(
                       HKEY_LOCAL_MACHINE,
                       wszConfigRegkeyWithID,
                       SHV_CONFIG_BLOB,
                       REG_DWORD,
                       (PVOID*)&dwIsChecked
                       );
  
      *bCount = (UINT16) sizeof(BYTE);
      *outdata = (BYTE*) CoTaskMemAlloc(sizeof(BYTE));
      if (*outdata)
      {
          **outdata = (BYTE)dwIsChecked;
      }
  
      return result;
  }
  
  STDMETHODIMP ShvUI::SetConfigToID(UINT32 configID, UINT16 bCount, BYTE* outdata)
  {
      if (!outdata)
      {
          return E_INVALIDARG;
      }
  
      if (configID == DEFAULT_CONFIGURATION_ID)
      {
          return SetConfig(bCount, outdata);
      }
  
      WCHAR wszConfigRegkeyWithID[MAX_PATH] = {0};
      AssembleRegkeyPathWithID(wszConfigRegkeyWithID, configID);
  
      if (bCount == sizeof(g_config))
      {
          // commit the cache
          BOOL isChecked = *outdata;
          ShvuiSetRegistryValue(
                          wszConfigRegkeyWithID,
                          NULL,
                          SHV_CONFIG_BLOB,
                          REG_DWORD,
                          (PBYTE)&isChecked,
                          sizeof(DWORD)
                          );
      }
      
      return S_OK;
  }
  
  DWORD
  ProcessCheckBox(
      HWND hDlg,
      int nIDCheckBox)
  {
      DWORD result = ERROR_SUCCESS;
      BOOL isChecked = FALSE;
  
      isChecked = (BST_CHECKED == (BOOL)IsDlgButtonChecked(
                                                   hDlg,
                                                   nIDCheckBox
                                                   ));
      if(nIDCheckBox == IDC_SDKSHV_FW)
      {
          if (!g_fConfigModeMemoryOnly)
          {
              result = ShvuiSetRegistryValue(
                  SDKSHV_DEFAULT_CONFIG_KEY,
                  NULL,
                  SHV_CONFIG_BLOB,
                  REG_DWORD,
                  (PBYTE)&isChecked,
                  sizeof(DWORD));
          } 
          else
          {
              if(isChecked)
              {
                  g_config = 1;
              }
              else
              {
                  g_config = 0;
              }
          }
      }
  
      return result;
  }
  
  DWORD
  OnClickOk(HWND hDlg)
  {
      DWORD result = ERROR_SUCCESS;
      
      result = ProcessCheckBox(
              hDlg,
              IDC_SDKSHV_FW);
      DEBUGLOGRESULT(L"OnClickOk-ProcessCheckBox(IDC_SHV_FW)", result);
  
  cleanup:    
      return result;
  }
  
  
  DWORD
  InitializeCheckBoxes(HWND hDlg)
  {
      DWORD result = ERROR_SUCCESS;
      DWORD dwIsChecked = FALSE;
  
      if (g_fConfigModeMemoryOnly)
      {
           dwIsChecked = g_config;
      }
      else
      {
           result = ShvuiGetRegistryValue(
                           HKEY_LOCAL_MACHINE,
                           SDKSHV_DEFAULT_CONFIG_KEY,
                           SHV_CONFIG_BLOB,
                           REG_DWORD,
                           (PVOID*)&dwIsChecked
                           );
      }
  
      // if the value is not present, we will try and set a defautl value of 1    
      if (result == ERROR_FILE_NOT_FOUND)
      {
          dwIsChecked = TRUE;
          result = ShvuiSetRegistryValue(
                          SDKSHV_DEFAULT_CONFIG_KEY,
                          NULL,
                          SHV_CONFIG_BLOB,
                          REG_DWORD,
                          (PBYTE)&dwIsChecked,
                          sizeof(DWORD));
  
          DEBUGLOGRESULT(L"SetCheckBox-ShvuiSetRegistryValue", result);        
      }
      else
      {
          DEBUGLOGRESULT(L"SetCheckBox-ShvuiGetRegistryValue", result);        
      }
  
      if (dwIsChecked == TRUE)
      {
          if (FALSE == CheckDlgButton(
                  hDlg,
                  IDC_SDKSHV_FW,
                  (dwIsChecked == TRUE) ? BST_CHECKED : BST_UNCHECKED
                  ))
              {
                  result = GetLastError();
              }
      }
  
  cleanup:
      return result;
  
  }
  
  static BOOLEAN bInitializing = TRUE;
  
  // DlgProc
  INT_PTR CALLBACK DlgProcSHVPage(
               HWND hDlg, 
               UINT message, 
               WPARAM wParam, 
               LPARAM //lParam
               )
  {    
      DWORD result = ERROR_SUCCESS;
      
      //
      // process message
      //    
      switch(message)
      {
  
          case WM_INITDIALOG:
              // read from the registries and set the check boxes as appropriate
              InitializeCheckBoxes(hDlg);
              bInitializing = FALSE;
              return TRUE;
  
          case WM_COMMAND:
  
              switch(LOWORD(wParam))
              {
                  //Ignore check-boxes, these are processed in OnClickOK()
                  case IDC_SDKSHV_FW:
                      return TRUE;
  
                  case IDOK:
                      result = OnClickOk(hDlg);
                      if(ERROR_SUCCESS == result)
                      {
                          EndDialog(hDlg, 0);
                      }
                      return TRUE;
                      
                  case IDAPPLY:
                      result = OnClickOk(hDlg);
                      break;
                      
                  case IDCANCEL:
                      // end the dialog
                      EndDialog(hDlg, 0);
                      return TRUE;
                      
                  default:
                      break;
              }
              break;
  
          case WM_QUIT:
              // end the dialog
                EndDialog(hDlg, 0);
  		return TRUE;
          default:
              break;                
      }
      return FALSE;
  }
  
  void AssembleRegkeyPathWithID (__out_ecount(MAX_PATH) LPTSTR pwszConfigRegkeyWithID, __in UINT32 uConfigID)
  {    
      ZeroMemory(pwszConfigRegkeyWithID, MAX_PATH);
      WCHAR wszConfigID[20] = {0};
      StringCchPrintf (wszConfigID, 20, L"\\%u", uConfigID);
      StringCchCopy (pwszConfigRegkeyWithID, MAX_PATH, SDKSHV_MULTI_CONFIG_KEY);
      StringCchCat  (pwszConfigRegkeyWithID, MAX_PATH, wszConfigID);
  }