home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / dcom / secure / secclnt.cpp < prev    next >
C/C++ Source or Header  |  1996-07-05  |  25KB  |  590 lines

  1. // ===========================================================================
  2. // File: S E C C L N T . C P P
  3. // 
  4. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  5. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  6. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  7. // PARTICULAR PURPOSE.
  8. //
  9. // Description:
  10. // 
  11. //  This is the client-portion of the SECURE Network OLE sample. This
  12. // application displays UI to allow you to select security settings for
  13. // the client process's connections to the server, connect to local or remote
  14. // instances of either the "LocalServer32" (CLSID_SecureObject) or "LocalService"
  15. // (CLSID_SecureObjectService) objects.
  16. // 
  17. //  The purpose of this sample is to demonstrate client-side security
  18. // capabilities.
  19. // 
  20. // Instructions:
  21. // 
  22. //  To use this sample:
  23. //   * build the samples using the NMAKE command. NMAKE will create SECCLNT.EXE,
  24. //     SECSVR.EXE, and PSMYPROP.DLL. PSMYPROP.DLL is the remoting proxies and
  25. //     stubs for the custom interface used between the client and the server.
  26. //   * install the server on the current machine or on a remote machine
  27. //     by running INSTALL.BAT in the same directory with SECSVR.EXE and
  28. //     PSMYPROP.DLL. This program registers the proxy-stub DLL using the
  29. //     REGSVR32 tool (included in the \mstools\bin directory of the SDK) and
  30. //     runs the SECSVR.EXE program with "-AutoRegister" on the command-line,
  31. //     which forces it to install itself.
  32. //   * next, run SECCLNT.EXE. it will bring up a user interface with 3 different
  33. //     sections.
  34. //   * In Section 1, choose the security parameters to CoInitializeSecurity from
  35. //     the two drop-down lists, and press the Initialize button.
  36. //   * Next, in Section 2, choose a machine name to instantiate the object on
  37. //     (leave this field blank to use the current machine) and choose between the
  38. //     "LocalService" or the standard "LocalServer32" implementation of the object.
  39. //     Then, press the "Create Now" button to create an instance.
  40. //   * With some security settings, you will receive a message box at this point
  41. //     telling you that the connection to the object has no authentication. In this
  42. //     case, the call-level security choices in Section 3 will not be made available.
  43. //   * Next, go to Section 3 and set the color and the "Name" on the object.
  44. //     These UI elements make calls on the custom IMyProperties interface. If you
  45. //     have pre-launched SECSVR.EXE with the "-Interactive" flag on the local or
  46. //     remote machine that you are connected to, you will be able to see the
  47. //     changes you make to the color and the name reflected in its UI, and may
  48. //     adjust some simple security settings (see the Instructions section of
  49. //     SECSVR.CPP for details).
  50. //   * Push the "Release" button in Section 2 to release the object and connect to
  51. //     a different object. When you are done, close the dialog box or push the
  52. //     "Exit" button in Section 1 at any time to exit.
  53. // 
  54. // Copyright 1996 Microsoft Corporation. All Rights Reserved.
  55. // ===========================================================================
  56.  
  57. // %%Includes: ---------------------------------------------------------------
  58. #define INC_OLE2
  59. #define UNICODE
  60. #include <windows.h>
  61. #include <initguid.h>
  62. #include "myprop.h"
  63. #include <rpcdce.h>
  64. #include "secclnt.h"
  65.  
  66. // %%Macros: -----------------------------------------------------------------
  67. #define ENTRY(sz, val)      { sz, val }
  68. #define RGSIZEOF(rg)        (sizeof(rg)/sizeof((rg)[0]))
  69.  
  70. // %%Constants: --------------------------------------------------------------
  71. #define cServerEntries      RGSIZEOF(rgServerEntries)
  72. #define cAuthnLevelEntries  RGSIZEOF(rgAuthnLevelEntries)
  73. #define cAuthzEntries       RGSIZEOF(rgAuthzEntries)
  74. #define cImpLevelEntries    RGSIZEOF(rgImpLevelEntries)
  75. #define cAuthnEntries       RGSIZEOF(rgAuthnEntries)
  76.  
  77. // %%Types: ------------------------------------------------------------------
  78. typedef struct tagENTRY{
  79.     TCHAR   *szName;
  80.     DWORD   dwVal;
  81. } ENTRY, *PENTRY;
  82.  
  83. // %%Globals: ----------------------------------------------------------------
  84. COLORREF s_crCurrent;
  85. HBRUSH   s_hbrCurrent = NULL;
  86.  
  87. ENTRY   rgServerEntries[] = {
  88.     ENTRY(TEXT("Secure Object"), (DWORD)(LPVOID)&CLSID_SecureObject),
  89.     ENTRY(TEXT("Secure Object Service"), (DWORD)(LPVOID)&CLSID_SecureObjectService),
  90.     };
  91.  
  92. ENTRY   rgAuthnLevelEntries[] = {
  93.     ENTRY(TEXT("Default    "), RPC_C_AUTHN_DEFAULT),
  94.     ENTRY(TEXT("None       "), RPC_C_AUTHN_LEVEL_NONE),
  95.     ENTRY(TEXT("Connect    "), RPC_C_AUTHN_LEVEL_CONNECT),
  96.     ENTRY(TEXT("Call       "), RPC_C_AUTHN_LEVEL_CALL),
  97.     ENTRY(TEXT("Packet     "), RPC_C_AUTHN_LEVEL_PKT),
  98.     ENTRY(TEXT("Integrity  "), RPC_C_AUTHN_LEVEL_PKT_INTEGRITY),
  99.     ENTRY(TEXT("Privacy    "), RPC_C_AUTHN_LEVEL_PKT_PRIVACY),
  100.     };
  101. ENTRY   rgAuthzEntries[] = {
  102.     ENTRY(TEXT("None       "), RPC_C_AUTHZ_NONE),
  103.     ENTRY(TEXT("Name       "), RPC_C_AUTHZ_NAME),
  104.     ENTRY(TEXT("DCE        "), RPC_C_AUTHZ_DCE),
  105.     };
  106.  
  107. ENTRY   rgImpLevelEntries[] = {
  108.     ENTRY(TEXT("Anonymous  "), RPC_C_IMP_LEVEL_ANONYMOUS),
  109.     ENTRY(TEXT("Identify   "), RPC_C_IMP_LEVEL_IDENTIFY),
  110.     ENTRY(TEXT("Impersonate"), RPC_C_IMP_LEVEL_IMPERSONATE),
  111.     ENTRY(TEXT("Delegate   "), RPC_C_IMP_LEVEL_DELEGATE),
  112.     };
  113.  
  114. ENTRY   rgAuthnEntries[] = {
  115.     ENTRY(TEXT("None       "), RPC_C_AUTHN_NONE),
  116.     ENTRY(TEXT("DCE Private"), RPC_C_AUTHN_DCE_PRIVATE),
  117.     ENTRY(TEXT("DCE Public "), RPC_C_AUTHN_DCE_PUBLIC),
  118.     ENTRY(TEXT("DEC Public "), RPC_C_AUTHN_DEC_PUBLIC),
  119.     ENTRY(TEXT("Windows NT "), RPC_C_AUTHN_WINNT),
  120.     ENTRY(TEXT("Default    "), RPC_C_AUTHN_DEFAULT),
  121.     };
  122.  
  123. // ---------------------------------------------------------------------------
  124. // %%Function: ErrorMessage
  125. // ---------------------------------------------------------------------------
  126.  void
  127. ErrorMessage(HWND hwnd, LPTSTR szFunction, HRESULT hr)
  128. {
  129.     LPTSTR   szMessage;
  130.  
  131.     if (HRESULT_FACILITY(hr) == FACILITY_WINDOWS)
  132.         hr = HRESULT_CODE(hr);
  133.  
  134.     FormatMessage(
  135.         FORMAT_MESSAGE_ALLOCATE_BUFFER |
  136.         FORMAT_MESSAGE_FROM_SYSTEM,
  137.         NULL,
  138.         hr,
  139.         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language
  140.         (LPTSTR)&szMessage,
  141.         0,
  142.         NULL );
  143.  
  144.     MessageBox(hwnd, szMessage, szFunction, MB_OK);
  145.     
  146.     LocalFree(szMessage);
  147. }  // ErrorMessage
  148.  
  149. // ---------------------------------------------------------------------------
  150. // %%Function: SelectEntry
  151. // ---------------------------------------------------------------------------
  152.  void
  153. SelectEntry(HWND hwnd, ENTRY* rgEntries, int cEntries, DWORD dwVal)
  154. {
  155.     for (int i=0; i<cEntries; i++)
  156.         {
  157.         if (rgEntries[i].dwVal == dwVal)
  158.             {
  159.             SendMessage(hwnd, CB_SETCURSEL, i, 0);
  160.             return;
  161.             }
  162.         }
  163. }  // SelectEntry
  164.  
  165. // ---------------------------------------------------------------------------
  166. // %%Function: GetField
  167. // ---------------------------------------------------------------------------
  168.  DWORD
  169. GetField(HWND hwndDlg, UINT idItem)
  170. {
  171.     HWND    hwnd;
  172.     int     iCur;
  173.  
  174.     hwnd = GetDlgItem(hwndDlg, idItem);
  175.     iCur = SendMessage(hwnd, CB_GETCURSEL, 0, 0);
  176.     return SendMessage(hwnd, CB_GETITEMDATA, iCur, 0);
  177. }  // GetField
  178.  
  179. // ---------------------------------------------------------------------------
  180. // %%Function: UpdateSecurityFields
  181. // ---------------------------------------------------------------------------
  182.  void
  183. UpdateSecurityFields(HWND hwndDlg, LPUNKNOWN punk, BOOL fSet)
  184. {
  185.     HWND    hwnd;
  186.     DWORD   dwAuthn, dwAuthz, dwAuthnLevel, dwImpLevel;
  187.     LPOLESTR wszPrinciple;
  188.     HRESULT hr;
  189.  
  190.     // in response to a CBN_SELCHANGE, we try to set the new proxy
  191.     // security parameters first
  192.     if (fSet)
  193.         {
  194.         hr = CoSetProxyBlanket(punk,
  195.             GetField(hwndDlg, IDC_PROXY_AUTHN),
  196.             GetField(hwndDlg, IDC_PROXY_AUTHZ),
  197.             NULL,
  198.             GetField(hwndDlg, IDC_PROXY_AUTHNLEVEL),
  199.             GetField(hwndDlg, IDC_PROXY_IMPLEVEL),
  200.             NULL,
  201.             NULL);
  202.         if (FAILED(hr))
  203.             {
  204.             ErrorMessage(hwndDlg, TEXT("CoSetProxyBlanket"), hr);
  205.             }
  206.         }
  207.  
  208.     // in all cases, update the fields to reflect the actual state of
  209.     // security on the proxy
  210.     hr = CoQueryProxyBlanket(punk,
  211.         &dwAuthn, &dwAuthz, &wszPrinciple, &dwAuthnLevel, &dwImpLevel,
  212.         NULL, NULL);
  213.     if (FAILED(hr))
  214.         {
  215.         ErrorMessage(hwndDlg, TEXT("CoQueryProxyBlanket"), hr);
  216.         }
  217.     else
  218.         {
  219.         hwnd = GetDlgItem(hwndDlg, IDC_PROXY_AUTHN);
  220.         EnableWindow(hwnd, TRUE);
  221.         SelectEntry(hwnd, rgAuthnEntries, cAuthnEntries, dwAuthn);
  222.  
  223.         hwnd = GetDlgItem(hwndDlg, IDC_PROXY_AUTHZ);
  224.         EnableWindow(hwnd, TRUE);
  225.         SelectEntry(hwnd, rgAuthzEntries, cAuthzEntries, dwAuthz);
  226.  
  227.         hwnd = GetDlgItem(hwndDlg, IDC_PROXY_AUTHNLEVEL);
  228.         EnableWindow(hwnd, TRUE);
  229.         SelectEntry(hwnd, rgAuthnLevelEntries, cAuthnLevelEntries, dwAuthnLevel);
  230.  
  231.         hwnd = GetDlgItem(hwndDlg, IDC_PROXY_IMPLEVEL);
  232.         EnableWindow(hwnd, TRUE);
  233.         SelectEntry(hwnd, rgImpLevelEntries, cImpLevelEntries, dwImpLevel);
  234.  
  235.         SetWindowTextW(GetDlgItem(hwndDlg, IDC_PROXY_PRINCIPLENAME),
  236.             wszPrinciple);
  237.         }
  238. }  // UpdateSecurityFields
  239.  
  240. // ---------------------------------------------------------------------------
  241. // %%Function: UpdatePropertyFields
  242. // ---------------------------------------------------------------------------
  243.  void
  244. UpdatePropertyFields(HWND hwndDlg, LPMYPROPERTIES pmp)
  245. {
  246.     COLORREF    cr;
  247.     WCHAR       rgchUserName[20];
  248.     HRESULT     hr;
  249.  
  250.     hr = pmp->GetColor(&cr);
  251.     if (FAILED(hr))
  252.         {
  253.         ErrorMessage(hwndDlg, TEXT("Get Color"), hr);
  254.         }
  255.     else
  256.         {
  257.         s_crCurrent = cr;
  258.         if (s_hbrCurrent != NULL)
  259.             DeleteObject(s_hbrCurrent);
  260.         s_hbrCurrent = CreateSolidBrush(s_crCurrent);
  261.         InvalidateRect(GetDlgItem(hwndDlg, IDC_COLOR), NULL, TRUE);
  262.         }
  263.  
  264.     hr = pmp->GetUserName(rgchUserName);
  265.     if (FAILED(hr))
  266.         {
  267.         ErrorMessage(hwndDlg, TEXT("Get User Name"), hr);
  268.         }
  269.     else
  270.         {
  271.         SetWindowTextW(GetDlgItem(hwndDlg, IDC_USERNAME), rgchUserName);
  272.         }
  273. }  // UpdatePropertyFields
  274.  
  275. // ---------------------------------------------------------------------------
  276. // %%Function: ClientDialogProc
  277. // ---------------------------------------------------------------------------
  278.  BOOL CALLBACK
  279. ClientDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
  280. {
  281.     static BOOL s_fInitialized = FALSE;
  282.     static LPMYPROPERTIES s_pmp = NULL;
  283.     static COLORREF s_rgcrCustom[16];
  284.     HRESULT     hr;
  285.  
  286.     switch (message)
  287.         {
  288.         case WM_INITDIALOG:
  289.             {
  290.             HWND    hwnd1, hwnd2;
  291.             int     i, cxScreen, cyScreen;
  292.             RECT    rcDlg;
  293.  
  294.             cxScreen = GetSystemMetrics(SM_CXFULLSCREEN);
  295.             cyScreen = GetSystemMetrics(SM_CYFULLSCREEN);
  296.  
  297.             GetWindowRect(hwndDlg, &rcDlg);
  298.             OffsetRect(&rcDlg,
  299.                 (cxScreen - rcDlg.right - rcDlg.left)/2,
  300.                 (cyScreen - rcDlg.bottom - rcDlg.top)/2);
  301.  
  302.             MoveWindow(hwndDlg, rcDlg.left, rcDlg.top,
  303.                 rcDlg.right-rcDlg.left, rcDlg.bottom-rcDlg.top, TRUE);
  304.  
  305.             // build the list of servers, select the Remote Server by default
  306.             hwnd1 = GetDlgItem(hwndDlg, IDC_SERVER_CLASS);
  307.             for (i=0; i<cServerEntries; i++)
  308.                 {
  309.                 SendMessage(hwnd1, CB_INSERTSTRING, i, (LPARAM)rgServerEntries[i].szName);
  310.                 SendMessage(hwnd1, CB_SETITEMDATA, i, rgServerEntries[i].dwVal);
  311.                 }
  312.             SendMessage(hwnd1, CB_SETCURSEL, 0, 0);
  313.  
  314.             // build the lists of authentication levels. choose None for the
  315.             // process default. the proxy setting will be retrieved via CoQueryProxyBlanket
  316.             // once the object is instantiated
  317.             hwnd1 = GetDlgItem(hwndDlg, IDC_CLIENT_AUTHNLEVEL);
  318.             hwnd2 = GetDlgItem(hwndDlg, IDC_PROXY_AUTHNLEVEL);
  319.             for (i=0; i<cAuthnLevelEntries; i++)
  320.                 {
  321.                 SendMessage(hwnd1, CB_INSERTSTRING, i, (LPARAM)rgAuthnLevelEntries[i].szName);
  322.                 SendMessage(hwnd1, CB_SETITEMDATA, i, rgAuthnLevelEntries[i].dwVal);
  323.                 SendMessage(hwnd2, CB_INSERTSTRING, i, (LPARAM)rgAuthnLevelEntries[i].szName);
  324.                 SendMessage(hwnd2, CB_SETITEMDATA, i, rgAuthnLevelEntries[i].dwVal);
  325.                 }
  326.             SelectEntry(hwnd1, rgAuthnLevelEntries, cAuthnLevelEntries, RPC_C_AUTHN_LEVEL_NONE);
  327.  
  328.             // build the lists of impersonation levels. choose Anonymous for the
  329.             // process default. the proxy setting will be retrieved via CoQueryProxyBlanket
  330.             // once the object is instantiated
  331.             hwnd1 = GetDlgItem(hwndDlg, IDC_CLIENT_IMPLEVEL);
  332.             hwnd2 = GetDlgItem(hwndDlg, IDC_PROXY_IMPLEVEL);
  333.             for (i=0; i<cImpLevelEntries; i++)
  334.                 {
  335.                 SendMessage(hwnd1, CB_INSERTSTRING, i, (LPARAM)rgImpLevelEntries[i].szName);
  336.                 SendMessage(hwnd1, CB_SETITEMDATA, i, rgImpLevelEntries[i].dwVal);
  337.                 SendMessage(hwnd2, CB_INSERTSTRING, i, (LPARAM)rgImpLevelEntries[i].szName);
  338.                 SendMessage(hwnd2, CB_SETITEMDATA, i, rgImpLevelEntries[i].dwVal);
  339.                 }
  340.             SelectEntry(hwnd1, rgImpLevelEntries, cImpLevelEntries, RPC_C_IMP_LEVEL_ANONYMOUS);
  341.  
  342.             // build the list of authorization services. the actual setting will
  343.             // be retrieved via CoQueryProxyBlanket once the object is instantiated,
  344.             // and can be modified after that.
  345.             hwnd1 = GetDlgItem(hwndDlg, IDC_PROXY_AUTHZ);
  346.             for (i=0; i<cAuthzEntries; i++)
  347.                 {
  348.                 SendMessage(hwnd1, CB_INSERTSTRING, i, (LPARAM)rgAuthzEntries[i].szName);
  349.                 SendMessage(hwnd1, CB_SETITEMDATA, i, rgAuthzEntries[i].dwVal);
  350.                 }
  351.  
  352.             // build the list of authentication services. the actual setting will
  353.             // be retrieved via CoQueryProxyBlanket once the object is instantiated,
  354.             // and can be modified after that.
  355.             hwnd1 = GetDlgItem(hwndDlg, IDC_PROXY_AUTHN);
  356.             for (i=0; i<cAuthnEntries; i++)
  357.                 {
  358.                 SendMessage(hwnd1, CB_INSERTSTRING, i, (LPARAM)rgAuthnEntries[i].szName);
  359.                 SendMessage(hwnd1, CB_SETITEMDATA, i, rgAuthnEntries[i].dwVal);
  360.                 }
  361.             return 1;
  362.             }
  363.  
  364.         case WM_SYSCOMMAND:
  365.             if (wParam == SC_CLOSE)
  366.                 goto LClose;
  367.             break;
  368.  
  369.         case WM_COMMAND:
  370.             if (HIWORD(wParam) == CBN_SELCHANGE && s_pmp != NULL)
  371.                 {
  372.                 UpdateSecurityFields(hwndDlg, s_pmp, TRUE);
  373.                 }
  374.             switch (LOWORD(wParam))
  375.                 {
  376.                 case IDCANCEL:
  377. LClose:
  378.                     if (s_pmp != NULL)
  379.                         {
  380.                         s_pmp->Release();
  381.                         s_pmp = NULL;
  382.                         }
  383.                     if (s_fInitialized == TRUE)
  384.                         {
  385.                         CoUninitialize();
  386.                         s_fInitialized = FALSE;
  387.                         }
  388.                     if (s_hbrCurrent != NULL)
  389.                         {
  390.                         DeleteObject(s_hbrCurrent);
  391.                         s_hbrCurrent = NULL;
  392.                         }
  393.                     EndDialog(hwndDlg, 0);
  394.                     break;
  395.  
  396.                 case IDC_INITIALIZE:
  397.                     hr = CoInitialize(NULL);
  398.                     if (FAILED(hr))
  399.                         {
  400.                         ErrorMessage(hwndDlg, TEXT("CoInitialize"), hr);
  401.                         }
  402.                     else
  403.                         {
  404.                         hr = CoInitializeSecurity(NULL,
  405.                             -1,
  406.                             NULL,
  407.                             NULL,
  408.                             GetField(hwndDlg, IDC_CLIENT_AUTHNLEVEL),
  409.                             GetField(hwndDlg, IDC_CLIENT_IMPLEVEL),
  410.                             NULL,
  411.                             0,
  412.                             NULL);
  413.                         if (FAILED(hr))
  414.                             {
  415.                             ErrorMessage(hwndDlg, TEXT("CoInitializeSecurity"), hr);
  416.                             }
  417.                         else
  418.                             {
  419.                             // Disable Initialization Step (#1)
  420.                             EnableWindow(GetDlgItem(hwndDlg, IDC_INITIALIZE), FALSE);
  421.                             EnableWindow(GetDlgItem(hwndDlg, IDC_CLIENT_AUTHNLEVEL), FALSE);
  422.                             EnableWindow(GetDlgItem(hwndDlg, IDC_CLIENT_IMPLEVEL), FALSE);
  423.  
  424.                             // Enable Object Creation Step (#2)
  425.                             EnableWindow(GetDlgItem(hwndDlg, IDC_SERVER_CLASS), TRUE);
  426.                             EnableWindow(GetDlgItem(hwndDlg, IDC_MACHINENAME), TRUE);
  427.                             EnableWindow(GetDlgItem(hwndDlg, IDC_CREATE), TRUE);
  428.                             s_fInitialized = TRUE;
  429.                             }
  430.                         }
  431.                     break;
  432.                         
  433.                 case IDC_CREATE:
  434.                     {
  435.                     OLECHAR rgchName[MAX_PATH];
  436.                     LPCLASSFACTORY  pcf;
  437.                     COSERVERINFO    csi, *pcsi;
  438.                     CLSID   *pclsid;
  439.                     HWND    hwnd;
  440.                     int     iCur;
  441.  
  442.                     // retrieve the class to instantiate
  443.                     hwnd = GetDlgItem(hwndDlg, IDC_SERVER_CLASS);
  444.                     iCur = SendMessage(hwnd, CB_GETCURSEL, 0, 0);
  445.                     pclsid = (LPCLSID)SendMessage(hwnd, CB_GETITEMDATA, iCur, 0);
  446.  
  447.                     // retrieve the machine name to run the server on. if this
  448.                     // is blank or ".", instantiate locally by passing a NULL ComServerInfo
  449.                     memset(&csi, 0, sizeof(COSERVERINFO));
  450.                     csi.pwszName = rgchName;
  451.                     GetWindowTextW(GetDlgItem(hwndDlg, IDC_MACHINENAME),
  452.                         rgchName, RGSIZEOF(rgchName));
  453.                     if (lstrlenW(rgchName) == 0 || lstrcmpiW(rgchName, L".") == 0)
  454.                         pcsi = NULL;
  455.                     else
  456.                         pcsi = &csi;
  457.  
  458.                     // create the object
  459.                     hr = CoGetClassObject(*pclsid, CLSCTX_SERVER,
  460.                         pcsi, IID_IClassFactory, (void**)&pcf);
  461.                     if (FAILED(hr))
  462.                         {
  463.                         ErrorMessage(hwndDlg, TEXT("CoGetClassObject"), hr);
  464.                         break;
  465.                         }
  466.                     hr = pcf->CreateInstance(NULL, IID_IMyProperties, (void**)&s_pmp);
  467.                     pcf->Release();
  468.                     if (FAILED(hr))
  469.                         {
  470.                         ErrorMessage(hwndDlg, TEXT("IClassFactory::CreateInstance"), hr);
  471.                         break;
  472.                         }
  473.  
  474.                     // Allow a different instance to get created only if the Release
  475.                     // button is pushed first
  476.                     EnableWindow(GetDlgItem(hwndDlg, IDC_CREATE), FALSE);
  477.                     EnableWindow(GetDlgItem(hwndDlg, IDC_SERVER_CLASS), FALSE);
  478.                     EnableWindow(GetDlgItem(hwndDlg, IDC_MACHINENAME), FALSE);
  479.                     EnableWindow(GetDlgItem(hwndDlg, IDC_RELEASE), TRUE);
  480.  
  481.                     // Enable manipulation of the object's properties. Allow
  482.                     // this even if the values of the object's call-security
  483.                     // parameters can not be determined, due to errors in
  484.                     // UpdateSecurityFields
  485.                     EnableWindow(GetDlgItem(hwndDlg, IDC_CHOOSECOLOR), TRUE);
  486.                     EnableWindow(GetDlgItem(hwndDlg, IDC_USERNAME), TRUE);
  487.  
  488.                     UpdateSecurityFields(hwndDlg, s_pmp, FALSE);
  489.                     UpdatePropertyFields(hwndDlg, s_pmp);
  490.                     break;
  491.                     }
  492.  
  493.                 case IDC_RELEASE:
  494.                     s_pmp->Release();
  495.                     s_pmp = NULL;
  496.  
  497.                     // Disable manipulating the properties and selecting the call
  498.                     // security parameters
  499.                     EnableWindow(GetDlgItem(hwndDlg, IDC_CHOOSECOLOR), FALSE);
  500.                     EnableWindow(GetDlgItem(hwndDlg, IDC_USERNAME), FALSE);
  501.                     EnableWindow(GetDlgItem(hwndDlg, IDC_PROXY_AUTHN), FALSE);
  502.                     EnableWindow(GetDlgItem(hwndDlg, IDC_PROXY_AUTHN), FALSE);
  503.                     EnableWindow(GetDlgItem(hwndDlg, IDC_PROXY_AUTHNLEVEL), FALSE);
  504.                     EnableWindow(GetDlgItem(hwndDlg, IDC_PROXY_IMPLEVEL), FALSE);
  505.  
  506.                     // Enable a new object to be created
  507.                     EnableWindow(GetDlgItem(hwndDlg, IDC_RELEASE), FALSE);
  508.                     EnableWindow(GetDlgItem(hwndDlg, IDC_CREATE), TRUE);
  509.                     EnableWindow(GetDlgItem(hwndDlg, IDC_SERVER_CLASS), TRUE);
  510.                     EnableWindow(GetDlgItem(hwndDlg, IDC_MACHINENAME), TRUE);
  511.                     break;
  512.  
  513.                 case IDC_CHOOSECOLOR:
  514.                     {
  515.                     CHOOSECOLOR cc;
  516.  
  517.                     cc.lStructSize = sizeof(CHOOSECOLOR);
  518.                     cc.hwndOwner = hwndDlg;
  519.                     cc.rgbResult = s_crCurrent;
  520.                     cc.lpCustColors = s_rgcrCustom;
  521.                     cc.Flags = CC_RGBINIT | CC_SHOWHELP;
  522.  
  523.                     if (ChooseColor(&cc))
  524.                         {
  525.                         hr = s_pmp->PutColor(cc.rgbResult);
  526.                         if (FAILED(hr))
  527.                             {
  528.                             ErrorMessage(hwndDlg, TEXT("Put Color"), hr);
  529.                             }
  530.                         else
  531.                             {
  532.                             UpdatePropertyFields(hwndDlg, s_pmp);
  533.                             }
  534.                         }
  535.                     break;
  536.                     }
  537.  
  538.                 case IDC_USERNAME:
  539.                     {
  540.                     static s_fDirty = FALSE;
  541.  
  542.                     if (HIWORD(wParam) == EN_CHANGE)
  543.                         {
  544.                         s_fDirty = TRUE;
  545.                         }
  546.                     else if (HIWORD(wParam) == EN_KILLFOCUS && s_fDirty)
  547.                         {
  548.                         WCHAR   rgchUserName[20];
  549.  
  550.                         GetWindowTextW(GetDlgItem(hwndDlg, IDC_USERNAME), rgchUserName, 20);
  551.                         hr = s_pmp->PutUserName(rgchUserName);
  552.                         if (FAILED(hr))
  553.                             ErrorMessage(hwndDlg, TEXT("Put User Name"), hr);
  554.                         UpdatePropertyFields(hwndDlg, s_pmp);
  555.                         s_fDirty = FALSE;
  556.                         }
  557.                     break;
  558.                     }
  559.                 }
  560.             break;
  561.  
  562.         case WM_DRAWITEM:
  563.             {
  564.             LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
  565.  
  566.             FillRect(lpdis->hDC, &lpdis->rcItem,
  567.                 s_hbrCurrent != NULL ? s_hbrCurrent : (HBRUSH)GetStockObject(WHITE_BRUSH));
  568.             FrameRect(lpdis->hDC, &lpdis->rcItem, (HBRUSH)GetStockObject(BLACK_BRUSH));
  569.             if (lpdis->itemState & ODS_SELECTED)
  570.                 InvertRect(lpdis->hDC, (LPRECT)&lpdis->rcItem);
  571.             if (lpdis->itemState & ODS_FOCUS)
  572.                 DrawFocusRect(lpdis->hDC, (LPRECT) &lpdis->rcItem);
  573.             return TRUE;
  574.             }
  575.         }
  576.     return FALSE;
  577. }  // ClientDialogProc
  578.  
  579. // ---------------------------------------------------------------------------
  580. // %%Function: WinMain
  581. // ---------------------------------------------------------------------------
  582.  int WINAPI
  583. WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
  584. {
  585.     return DialogBox(hInstance, MAKEINTRESOURCE(IDD_SECCLNT), GetDesktopWindow(), (DLGPROC)ClientDialogProc);
  586. }  // WinMain
  587.  
  588. // EOF =======================================================================
  589.  
  590.