CONNECT.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:21k
源码类别:

Windows编程

开发平台:

Visual C++

  1. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright (C) 1993-1997  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  MODULE:   connect.c
  9. //
  10. //  PURPOSE:   Displays the "Connect" dialog box
  11. //
  12. //  FUNCTIONS:
  13. //    CmdConnect              - Displays the "Connect" dialog box
  14. //    Connect                 - Processes messages for "Connect" dialog box.
  15. //    MsgConnectInit          - Initializes edit controls
  16. //    MsgConnectReadyForWrite - Sends name registration message when connection
  17. //                              established with server
  18. //    MsgConnectCommand       - Process WM_COMMAND message sent to the connect box.
  19. //    CmdConnectDone          - Free the connect box and related data.
  20. //    CmdConnectNow           - Establishes connection to server.
  21. //    CmdConnectEnableOK      - Enables/Disables OK button when input data is
  22. //                              valid/invalid
  23. //
  24. //  COMMENTS:
  25. //
  26. //
  27. #include <windows.h>            // required for all Windows applications
  28. #include <windowsx.h>
  29. #include <wsipx.h>              // IPX sockets
  30. #include <wsnetbs.h>            // NetBIOS sockets
  31. #include <stdlib.h>
  32. #include <stdio.h>
  33. #include <nspapi.h>
  34. #include <svcguid.h>
  35. #include "globals.h"            // prototypes specific to this application
  36. #define WSN_READYFORWRITE   700 // dlg window message indicating the connection is ready to send on
  37. //   Function Definitions
  38. LRESULT CALLBACK Connect(HWND, UINT, WPARAM, LPARAM);
  39. LRESULT MsgConnectInit(HWND, UINT, WPARAM, LPARAM);
  40. LRESULT MsgConnectReadyForWrite(HWND, UINT, WPARAM, LPARAM);
  41. LRESULT MsgConnectCommand(HWND, UINT, WPARAM, LPARAM);
  42. LRESULT CmdConnectNow(HWND, WORD, WORD, HWND);
  43. LRESULT CmdConnectDone(HWND, WORD, WORD, HWND);
  44. LRESULT CmdConnectEnableOK(HWND, WORD, WORD, HWND);
  45. // Connect dialog message table definition.
  46. MSD rgmsdConnect[] =
  47. {
  48.     {WM_COMMAND,        MsgConnectCommand},
  49.     {WM_INITDIALOG,     MsgConnectInit},
  50.     {WSN_READYFORWRITE,  MsgConnectReadyForWrite}
  51. };
  52. MSDI msdiConnect =
  53. {
  54.     sizeof(rgmsdConnect) / sizeof(MSD),
  55.     rgmsdConnect,
  56.     edwpNone
  57. };
  58. // Connect dialog command table definition.
  59. CMD rgcmdConnect[] =
  60. {
  61.     {IDOK,        CmdConnectNow},
  62.     {IDCANCEL,    CmdConnectDone},
  63.     {CD_NAME,     CmdConnectEnableOK},
  64.     {CD_PROTOCOL, CmdConnectEnableOK},
  65.    {CD_SERVER,   CmdConnectEnableOK}
  66. };
  67. CMDI cmdiConnect =
  68. {
  69.     sizeof(rgcmdConnect) / sizeof(CMD),
  70.     rgcmdConnect,
  71.     edwpNone
  72. };
  73. // Module specific "globals"  Used when a variable needs to be
  74. // accessed in more than one handler function.
  75. HFONT hfontDlg;
  76. //
  77. //  FUNCTION: CmdConnect(HWND, WORD, WORD, HWND)
  78. //
  79. //  PURPOSE: Displays the "Connect" dialog box
  80. //
  81. //  PARAMETERS:
  82. //    hwnd      - Window handle
  83. //    wCommand  - IDM_CONNECT (unused)
  84. //    wNotify   - Notification number (unused)
  85. //    hwndCtrl  - NULL (unused)
  86. //
  87. //  RETURN VALUE:
  88. //
  89. //    Always returns 0 - Message handled
  90. //
  91. //  COMMENTS:
  92. //    To process the IDM_CONNECT message, call DialogBox() to display the
  93. //    Connect dialog box.
  94. LRESULT CmdConnect(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
  95. {
  96.     // Start dialog box
  97.     if(DialogBox(hInst, "ConnectBox", hwnd, (DLGPROC)Connect))
  98.     {
  99.         // We have a connection and have registered our name.  Set up Select dialog.
  100.         PostMessage(hwnd, WM_COMMAND, MAKELONG(IDM_SELECT,0), 0);
  101.         return 0;
  102.     }
  103.     // Connection failed - reset window title
  104.     SetWindowText(hwnd, szTitle);
  105.     return 0;
  106. }
  107. //
  108. //  FUNCTION: Connect(HWND, UINT, WPARAM, LPARAM)
  109. //
  110. //  PURPOSE:  Processes messages for "Connect" dialog box.
  111. //
  112. //  PARAMETERS:
  113. //    hdlg - window handle of the dialog box
  114. //    wMessage - type of message
  115. //    wparam - message-specific information
  116. //    lparam - message-specific information
  117. //
  118. //  RETURN VALUE:
  119. //    TRUE - message handled
  120. //    FALSE - message not handled
  121. //
  122. //  COMMENTS:
  123. //
  124. //     Gets connection information from user and then establishes a connection.
  125. //
  126. //     Connect when user clicks on the OK button.  Kill Dialog when connection
  127. //     established.
  128. //
  129. LRESULT CALLBACK Connect(HWND hdlg, UINT uMessage, WPARAM wparam, LPARAM lparam)
  130. {
  131.     return DispMessage(&msdiConnect, hdlg, uMessage, wparam, lparam);
  132. }
  133. //
  134. //  FUNCTION: MsgConnectInit(HWND, UINT, WPARAM, LPARAM)
  135. //
  136. //  PURPOSE: To center dialog, limit size of edit controls, and set up available protocols
  137. //           to connect with
  138. //
  139. //  PARAMETERS:
  140. //    hdlg - The window handling the message.
  141. //    uMessage - The message number. (unused).
  142. //    wparam - Message specific data (unused).
  143. //    lparam - Message specific data (unused).
  144. //
  145. //  RETURN VALUE:
  146. //    Always returns 0 - message handled.
  147. //
  148. //  COMMENTS:
  149. //    Set size of edit controls for the following
  150. //           Network  8  chars (4 2-digit hex numbers)
  151. //           Node     12 chars (6 2-digit hex numbers)
  152. //           Socket   4  chars (2 2-digit hex numbers)
  153. //
  154. LRESULT MsgConnectInit(HWND hdlg, UINT uMessage, WPARAM wparam, LPARAM lparam)
  155. {
  156.     int numStrucs;
  157.     int j, k;
  158.     int iProtBufSize = 0;
  159.    char outtext[80];
  160.     // Create a font to use
  161.     hfontDlg = CreateFont(14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  162.                           VARIABLE_PITCH | FF_SWISS, "");
  163.     // Center the dialog over the application window
  164.     CenterWindow (hdlg, GetWindow (hdlg, GW_OWNER));
  165.    // Call EnumProtocols with NULL buffer in order to determine size of buffer required
  166.    EnumProtocols(NULL, NULL, &iProtBufSize);
  167.     if (((LPVOID)lpProtBuf = VirtualAlloc(NULL,
  168.                                           iProtBufSize,
  169.                                           MEM_COMMIT,
  170.                                           PAGE_READWRITE)) == NULL)
  171.     {
  172.         // ERROR -- abort
  173.         return 0;
  174.     }
  175.     // Calling EnumProtocols with large enough buffer
  176.     if ((numStrucs = EnumProtocols(NULL, lpProtBuf, &iProtBufSize)) == SOCKET_ERROR)
  177.     {
  178.         // Error -- abort
  179.         return 0;
  180.     }
  181.    // Add every connection oriented protocol to protocol combo box
  182.     for (j = 0, k = 0; j < numStrucs; j++)
  183.     {
  184.         if ((lpProtBuf[j].dwServiceFlags & XP_CONNECTIONLESS) == 0)
  185.         {
  186.          wsprintf(outtext, "%2d: %s", k, lpProtBuf[j].lpProtocol);
  187.             SendMessage(GetDlgItem(hdlg, CD_PROTOCOL), CB_ADDSTRING, 0, (LPARAM)outtext);
  188.             goodprots[k++] = j; // Keep track of good protocols
  189.         }
  190.     }
  191.     // Limit size of edit controls
  192.     SendDlgItemMessage(hdlg, CD_NAME, EM_LIMITTEXT, 15, 0);
  193.     // Initialize Edit Controls
  194.     SetDlgItemText(hdlg, CD_NAME, szConnectName);
  195.     return (TRUE);
  196. }
  197. //
  198. //  FUNCTION: MsgConnectReadyForWrite(HWND, UINT, WPARAM, LPARAM)
  199. //
  200. //  PURPOSE: Receive notification of connected socket and register name
  201. //
  202. //  PARAMETERS:
  203. //    hwnd - The window handing the message.
  204. //    uMessage - The message number. (unused).
  205. //    wparam - Message specific data (unused).
  206. //    lparam - Message specific data (unused).
  207. //
  208. //  RETURN VALUE:
  209. //    Always returns 0 - message handled.
  210. //
  211. //  COMMENTS:
  212. //    Uses this DispCommand function defined in wndproc.c combined
  213. //    with the cmdiConnect structure defined in this file to handle
  214. //    the command messages for the Connect dialog box.
  215. //
  216. LRESULT MsgConnectReadyForWrite(HWND   hwnd,
  217.                                 UINT   uMessage,
  218.                                 WPARAM wparam,
  219.                                 LPARAM lparam)
  220. {
  221.     char outtext[80];
  222.     // Build our name
  223.     GetDlgItemText(hwnd, CD_NAME, MySock.name, sizeof(MySock.name));
  224.     // Build name registration packet
  225.     xferbuf.hdr.signature = MYSIGNATURE;                 // signature
  226.     xferbuf.hdr.length = REALLEN(MySock.name) + HDRSIZE;
  227.     lstrcpy(xferbuf.data, MySock.name);                  // copy name
  228.     xferbuf.hdr.command = REGISTER_NAME;                 // REGISTER_NAME command
  229.     // Lets send it
  230.     senddatamessage(MySock.sock, &xferbuf);
  231.     wsprintf(outtext, GetStringRes(IDS_CHAT_AVAIL), MySock.name);
  232.     SetWindowText(GetParent(hwnd), outtext);
  233.     EndDialog(hwnd, TRUE);          // Exit the dialog
  234.     DeleteObject (hfontDlg);
  235.     return (TRUE);
  236. }
  237. //
  238. //  FUNCTION: MsgConnectCommand(HWND, UINT, WPARAM, LPARAM)
  239. //
  240. //  PURPOSE: Process WM_COMMAND message sent to the Connect box.
  241. //
  242. //  PARAMETERS:
  243. //    hwnd - The window handing the message.
  244. //    uMessage - The message number. (unused).
  245. //    wparam - Message specific data (unused).
  246. //    lparam - Message specific data (unused).
  247. //
  248. //  RETURN VALUE:
  249. //    Always returns 0 - message handled.
  250. //
  251. //  COMMENTS:
  252. //    Uses this DispCommand function defined in wndproc.c combined
  253. //    with the cmdiConnect structure defined in this file to handle
  254. //    the command messages for the Connect dialog box.
  255. //
  256. LRESULT MsgConnectCommand(HWND   hwnd,
  257.                           UINT   uMessage,
  258.                           WPARAM wparam,
  259.                           LPARAM lparam)
  260. {
  261.     return DispCommand(&cmdiConnect, hwnd, wparam, lparam);
  262. }
  263. //
  264. //  FUNCTION: CmdConnectDone(HWND, WORD, HWND)
  265. //
  266. //  PURPOSE: Free the Connect box and related data.
  267. //
  268. //  PARAMETERS:
  269. //    hdlg - The window handling the command.
  270. //    wCommand - The command to be handled (unused).
  271. //    wNotify   - Notification number (unused)
  272. //    hwndCtrl - NULL (unused).
  273. //
  274. //  RETURN VALUE:
  275. //    Always returns TRUE.
  276. //
  277. //  COMMENTS:
  278. //    Cleans up sockets then calls EndDialog to finish the dialog session.
  279. //
  280. LRESULT CmdConnectDone(HWND hdlg, WORD wCommand, WORD wNotify, HWND hwndCtrl)
  281. {
  282.     closesocket(MySock.sock);      // Free any aborted socket resources
  283.     EndDialog(hdlg, FALSE);        // Exit Dialog -- rtrn false since no connection
  284.     return TRUE;
  285. }
  286. //
  287. //  FUNCTION: CmdConnectNow(HWND, WORD, HWND)
  288. //
  289. //  PURPOSE: Establish the connection
  290. //
  291. //  PARAMETERS:
  292. //    hdlg - The window handling the command.
  293. //    wCommand - The command to be handled (unused).
  294. //    wNotify   - Notification number (unused)
  295. //    hwndCtrl - NULL (unused).
  296. //
  297. //  RETURN VALUE:
  298. //    Always returns TRUE.
  299. //
  300. //  COMMENTS:
  301. //    Makes Connection calls
  302. //
  303. LRESULT CmdConnectNow(HWND hdlg, WORD wCommand, WORD wNotify, HWND hwndCtrl)
  304. {
  305.     int iIndex;
  306.     char outtext[80];
  307.     int numStrucs;
  308.    GUID guidNW = SVCID_NETWARE(NWCHATID);
  309.    GUID guidDNS = SVCID_TCP(DNSCHATID);
  310.     // Get protocol selected
  311.     iIndex = SendMessage(GetDlgItem(hdlg, CD_PROTOCOL), CB_GETCURSEL, 0, 0);
  312.    // ************************************************************************
  313.    //
  314.    //    Below we will be calling GetAddressByName with the RES_FIND_MULTIPLE
  315.    //    option in order to find a remote address to connect() to.  At this
  316.    //    point, GetAddressByName() only supports the DNS and the SAP/Bindery
  317.    //    name spaces.  Ultimately a single call to GetAddressByName will
  318.    //    query all available protocols and name spaces, but this requires a
  319.    //    central database which is currently not available.  In the mean time
  320.    //    we will make name space specific calls to GetAddressByName.
  321.    //
  322.    // ***********************************************************************
  323.     switch (lpProtBuf[goodprots[iIndex]].iAddressFamily)
  324.     {
  325.         case AF_IPX:
  326.           //  SAP/Bindery Name Space
  327.           dwCSABufsize = sizeof(CSABuf);
  328.             if (((numStrucs = GetAddressByName(0,  // GUID indicates name space so we don't need to specify
  329.                                                &guidNW, // GUID generated from NetWare service type
  330.                                                "GLOBCHAT", // Name of service to look for
  331.                                                NULL, // GUID implies IPX/SPX protocols
  332.                                                RES_FIND_MULTIPLE, // We might get multiple responses
  333.                                                NULL, // Not currently supported
  334.                                                CSABuf, // results buffer
  335.                                                &dwCSABufsize,  // size of results buffer
  336.                                                NULL,  // not supported
  337.                                                NULL)  // not supported
  338.                                                ) == SOCKET_ERROR) || (numStrucs == 0))
  339.             {
  340.                 // Error -- try another protocol.  We've got lots!
  341.                 MessageBox(hdlg, GetStringRes(IDS_ERR_SERVER_NOT_FOUND), NULL, MB_OK);
  342.                 EnableWindow(GetDlgItem(hdlg, IDOK), FALSE);
  343.                 SetFocus(GetDlgItem(hdlg, CD_PROTOCOL));
  344.                 return 0;
  345.             }
  346.             break;
  347.         case AF_INET:
  348.             //  DNS Name Space
  349.             // Static Name Space requires us to specify the host name
  350.             GetDlgItemText(hdlg, CD_SERVER, lpServName, sizeof(lpServName));
  351.          dwCSABufsize = sizeof(CSABuf);
  352.             if (((numStrucs = GetAddressByName(0,    // GUID indicates name space so we don't need to specify
  353.                                              &guidDNS, // GUID generated from TCP port number
  354.                                              lpServName, // Name of host to look for
  355.                                              NULL, // GUID implies UDP/TCP protocols
  356.                                              RES_FIND_MULTIPLE, // We might get multiple responses
  357.                                              NULL, // Not currently supported
  358.                                              CSABuf, // results buffer
  359.                                              &dwCSABufsize, // size of results buffer
  360.                                              NULL, // not supported
  361.                                              NULL) // not supported
  362.                                              ) == SOCKET_ERROR) || (numStrucs == 0))
  363.             {
  364.                 // Error -- try another protocol.  We've got lots!
  365.                 MessageBox(hdlg, GetStringRes(IDS_ERR_SERVER_NOT_FOUND), NULL, MB_OK);
  366.                 EnableWindow(GetDlgItem(hdlg, IDOK), FALSE);
  367.                 SetFocus(GetDlgItem(hdlg, CD_PROTOCOL));
  368.                 return 0;
  369.             }
  370.             break;
  371.         case AF_NETBIOS:
  372.          // NetBIOS name space???
  373.             // no netbios name space provider so fill in lpCSABuf ourselves
  374.             numStrucs = 1;
  375.             CSABuf[0].iSocketType = lpProtBuf[goodprots[iIndex]].iSocketType;
  376.             CSABuf[0].iProtocol = lpProtBuf[goodprots[iIndex]].iProtocol;
  377.             SET_NETBIOS_SOCKADDR(&NBAddr,
  378.                                  NETBIOS_GROUP_NAME,
  379.                                  "GLOBSERV",
  380.                                  0);
  381.            CSABuf[0].RemoteAddr.lpSockaddr = (LPSOCKADDR)&NBAddr;
  382.          CSABuf[0].RemoteAddr.iSockaddrLength = sizeof(NBAddr);
  383.             break;
  384.         default:
  385.           // We don't support anything else
  386.             MessageBox(hdlg,
  387.                        GetStringRes(IDS_ERR_NAMESPACE_NOT_SUPPORTED),
  388.                        NULL, MB_OK);
  389.             EnableWindow(GetDlgItem(hdlg, IDOK), FALSE);
  390.             SetFocus(GetDlgItem(hdlg, CD_PROTOCOL));
  391.             return 0;
  392.     }
  393.    // Populate SOCKDATA struct
  394.     MySock.type = lpProtBuf[goodprots[iIndex]].iSocketType;
  395.     MySock.protocol = lpProtBuf[goodprots[iIndex]].iProtocol;
  396.     SetDlgItemText(hdlg, CD_HELP, GetStringRes(IDS_CALLING_SOCKET));
  397.    // Call socket() using triple provided by EnumProtocols()
  398.     if((MySock.sock = socket(lpProtBuf[goodprots[iIndex]].iAddressFamily,
  399.                              lpProtBuf[goodprots[iIndex]].iSocketType,
  400.                              lpProtBuf[goodprots[iIndex]].iProtocol)) == INVALID_SOCKET)
  401.     {
  402.         // ERROR
  403.         wsprintf(outtext, GetStringRes(IDS_ERR_SOCKET_FAILED), WSAGetLastError());
  404.         SetDlgItemText(hdlg, CD_HELP, outtext);
  405.         return 0;
  406.     }
  407.     SetDlgItemText(hdlg, CD_HELP, GetStringRes(IDS_CALLING_CONNECT));
  408.    // Call connect() using info from GetAddressByName()
  409.     if (connect(MySock.sock,
  410.                 CSABuf[0].RemoteAddr.lpSockaddr,
  411.                 CSABuf[0].RemoteAddr.iSockaddrLength) == SOCKET_ERROR)
  412.     {
  413.         // ERROR
  414.         wsprintf(outtext,
  415.                  GetStringRes(IDS_ERR_CONNECT_FAILED), WSAGetLastError());
  416.         SetDlgItemText(hdlg, CD_HELP, outtext);
  417.         return 0;
  418.     }
  419.     // Signal for when we are ready for writing
  420.     SetDlgItemText(hdlg, CD_HELP, GetStringRes(IDS_WAITING_FOR_ACCEPT));
  421.    // Specify message to signal accepted socket
  422.     if (WSAAsyncSelect(MySock.sock, hdlg, WSN_READYFORWRITE, FD_WRITE) == SOCKET_ERROR)
  423.     {
  424.         wsprintf(outtext,
  425.                  GetStringRes(IDS_ERR_WSAASYNCSELECT), WSAGetLastError());
  426.         SetDlgItemText(hdlg, CD_HELP, outtext);
  427.         return 0;
  428.     }
  429.     return 0;
  430. }
  431. //
  432. //  FUNCTION: CmdConnectEnableOK(HWND, WORD, WORD, HWND)
  433. //
  434. //  PURPOSE: Enable/Disable OK button when input data is valid/invalid
  435. //
  436. //  PARAMETERS:
  437. //    hdlg - The window handling the command.
  438. //    wCommand - The command to be handled (unused).
  439. //    wNotify   - Notification number (unused)
  440. //    hwndCtrl - NULL (unused).
  441. //
  442. //  RETURN VALUE:
  443. //    Always returns TRUE.
  444. //
  445. //  COMMENTS:
  446. //    Checks for acceptable name and protocol.  We also need an acceptable
  447. //    machine name for TCP/IP protocol since DNS name space is static
  448. //
  449. LRESULT CmdConnectEnableOK(HWND hdlg, WORD wCommand, WORD wNotify, HWND hwndCtrl)
  450. {
  451.     char buf[128];
  452.    int iIndex;
  453.     // Is message a change notification?
  454.     if ((wNotify == CBN_SELCHANGE) || (wNotify == EN_CHANGE))
  455.     {
  456.         // Yes!, get protocol
  457.         iIndex = SendMessage(GetDlgItem(hdlg, CD_PROTOCOL), CB_GETCURSEL, 0, 0);
  458.       if (iIndex == LB_ERR)
  459.       {
  460.           // No protocol selected...OK disabled
  461.           EnableWindow(GetDlgItem(hdlg, IDOK), FALSE);
  462.           return TRUE;
  463.       }
  464.         // Protocol selected!  Check which one...
  465.         switch(lpProtBuf[goodprots[iIndex]].iAddressFamily)
  466.         {
  467.             case AF_IPX:
  468.             case AF_NETBIOS:
  469.                 // For IPX and NetBIOS, we don't need the machine name
  470.             // so hide that edit control
  471.                 ShowWindow(GetDlgItem(hdlg, CD_SERVER), SW_HIDE);
  472.                 ShowWindow(GetDlgItem(hdlg, CD_SERVER_TEXT), SW_HIDE);
  473.             // We already have a protocol selected.  Do we have a name?
  474.                 if(GetDlgItemText(hdlg, CD_NAME, buf, sizeof(buf)) >= 1)
  475.                 {
  476.                     // Yes, we have a name and a protocol.  Enable OK.
  477.                     EnableWindow(GetDlgItem(hdlg, IDOK), TRUE);
  478.                 }
  479.             else
  480.             {
  481.                 // We don't have a name.  Disable OK.
  482.                 EnableWindow(GetDlgItem(hdlg, IDOK), FALSE);
  483.             }
  484.                 return TRUE;
  485.             case AF_INET:
  486.              // For TCP/IP we need a protocol, name, and machine name
  487.             // in order for data to be valid
  488.             // Enable Machine name edit control and text
  489.                 ShowWindow(GetDlgItem(hdlg, CD_SERVER), SW_SHOW);
  490.             ShowWindow(GetDlgItem(hdlg, CD_SERVER_TEXT), SW_SHOW);
  491.             EnableWindow(GetDlgItem(hdlg, CD_SERVER), TRUE);
  492.             EnableWindow(GetDlgItem(hdlg, CD_SERVER_TEXT), TRUE);
  493.                 // We have a protocol selected.  Do we have a name and a server name
  494.                 if((GetDlgItemText(hdlg, CD_NAME, buf, sizeof(buf)) >= 1) &&
  495.                    (GetDlgItemText(hdlg, CD_SERVER, buf, sizeof(buf)) >= 1))
  496.                 {
  497.                     // YES!  Enable OK.
  498.                     EnableWindow(GetDlgItem(hdlg, IDOK), TRUE);
  499.                SendMessage(GetDlgItem(hdlg, IDOK), BM_SETSTYLE, (WPARAM) LOWORD(BS_DEFPUSHBUTTON), MAKELPARAM(TRUE, 0));
  500.                 }
  501.             else
  502.             {
  503.                 // No name or server name.  Disable OK.
  504.                 EnableWindow(GetDlgItem(hdlg, IDOK), FALSE);
  505.             }
  506.                 return TRUE;
  507.             default:
  508.                 // We only support DNS, SAP/Bindery, and we simulate NetBIOS name spaces.
  509.                 SetDlgItemText(hdlg, CD_HELP,
  510.                                GetStringRes(IDS_ERR_UNSUPPORTED_PROTOCOL));
  511.                 EnableWindow(GetDlgItem(hdlg, IDOK), FALSE);
  512.                 return TRUE;
  513.         }
  514.     }
  515.     // When protocol combo box gets the focus, set help text at bottom of dialog
  516.     if (wNotify == CBN_SETFOCUS)
  517.     {
  518.         SetDlgItemText(hdlg, CD_HELP,
  519.                        GetStringRes(IDS_SELECT_PROTOCOL));
  520.     }
  521.     if (wNotify == EN_SETFOCUS)
  522.     {
  523.         if (hwndCtrl == GetDlgItem(hdlg, CD_NAME))
  524.         {
  525.             // When name edit control gets the focus, set help text at bottom of dialog.
  526.             SetDlgItemText(hdlg, CD_HELP, GetStringRes(IDS_ENTER_NAME));
  527.         }
  528.         else
  529.         {
  530.             // When server edit control gets the focus, set help text at bottom of dialog.
  531.             SetDlgItemText(hdlg, CD_HELP, GetStringRes(IDS_ENTER_MACHINE_NAME));
  532.         }
  533.     }
  534.     return TRUE;
  535. }