home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / dbmsg / mapi / remote.srv / admin.cpp < prev    next >
C/C++ Source or Header  |  1996-04-11  |  48KB  |  1,316 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  File Name 
  4. //      ADMIN.CPP
  5. //
  6. //  Description
  7. //
  8. //  Author
  9. //      Irving De la Cruz
  10. //
  11. //  Revision: 1.7
  12. //
  13. // Written for Microsoft Windows Developer Support
  14. // Copyright (c) 1995-1996 Microsoft Corporation. All rights reserved.
  15. //
  16. #include "ADMIN.H"
  17. #include "COMMON.H"
  18.  
  19. extern "C"
  20. {
  21.     TCHAR g_szAppTitle[] = TEXT("WINDS Administrator");
  22.     ITEM_TYPE g_LVItemsType = ITEM_UNDEFINED_TYPE;
  23.     HINSTANCE ghInstance = NULL;
  24.     HANDLE ghMemHeap = NULL;
  25.     HANDLE ghCancelEvent;
  26.     HWND ghTreeView, ghListView, ghWnd, ghStatusBar, ghToolBar;
  27.     BOOL gfCancel = FALSE, gfTerminate = FALSE;
  28.     HFONT ghBoldFont = NULL;
  29.     CRITICAL_SECTION csCancel, csRemoteServer;
  30.     TCHAR g_szCurrentServer[64] = { 0 };
  31.     HIMAGELIST g_hImages = NULL, g_hIconImgs = NULL;
  32.     LPVOID g_pctl3d = NULL;
  33.  
  34.     HRESULT WINAPI ServerChanged
  35.                         (HWND                       hTreeView);
  36.  
  37.     LRESULT CALLBACK MainWndProc
  38.                         (HWND                       hDlg, 
  39.                          UINT                       message, 
  40.                          WPARAM                     wParam, 
  41.                          LPARAM                     lParam);
  42.     BOOL WINAPI ShowConnectDialog
  43.                         (HWND                       hOwnerWnd,
  44.                          LPTSTR                     szServer,
  45.                          BOOL *                     pfServerIsOnLine);
  46.     BOOL WINAPI IsValidServerName
  47.                         (LPTSTR                     szServerName);
  48.     void WINAPI LoadSettingsFromRegistry
  49.                         (LPTSTR                     szServer);
  50.     void WINAPI SaveSettingsToRegistry
  51.                         (LPTSTR                     szServer);
  52.     void WINAPI HandleItemAction
  53.                         (HWND                       hOwnerWnd,
  54.                          int                        nItem,
  55.                          WORD                       wAction);
  56.     void WINAPI GetServerNameFromTitle
  57.                         (LPTSTR                     szItemTitle,
  58.                          LPTSTR *                   pszServerName);
  59.     HRESULT WINAPI CancelThreadProc
  60.                         ();
  61. }
  62.  
  63. CNotifLink * gpLink = NULL;
  64.  
  65. ///////////////////////////////////////////////////////////////////////////////
  66. //    WinMain()
  67. //
  68. //    Parameters
  69. //      { Refer to Win32 SDK documentation }
  70. //      
  71. //    Purpose
  72. //      This is the entry function. The application will start executing here.
  73. //      
  74. //    Return Value
  75. //      Return code of the application to the system.
  76. //      
  77. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pszCmdLine, int nCmdLine)
  78. {
  79.     #define WINDOW_CLASSNAME        TEXT("WINDS_ADMIN_CLASS")
  80.     // Check for other instances of this application running. If one is found,
  81.     // bring it to the foreground
  82.     ghWnd = FindWindow (WINDOW_CLASSNAME, NULL);
  83.     if (NULL != ghWnd)
  84.     {
  85.         HWND hChildWnd;
  86.         hChildWnd = GetLastActivePopup (ghWnd);
  87.         if (hChildWnd != ghWnd)
  88.         {
  89.             BringWindowToTop (hChildWnd);
  90.         }
  91.         else
  92.         {
  93.             SetForegroundWindow (ghWnd);
  94.         }
  95.         return 0;
  96.     }
  97.  
  98.     MSG msg;
  99.     HACCEL hAccel;
  100.     InitTraces (0);
  101.     TraceMessage ("WINDS Admin is initializing");
  102.     ghInstance = hInstance;
  103.     ghMemHeap = GetProcessHeap();
  104.  
  105.     WNDCLASS wc = { 0 };
  106.     // Register the class for this application
  107.     wc.lpfnWndProc      = MainWndProc;
  108.     wc.hInstance        = ghInstance;
  109.     wc.hIcon            = LoadIcon (ghInstance, MAKEINTRESOURCE (IDI_MAINFRAME));
  110.     wc.lpszMenuName     = MAKEINTRESOURCE (IDM_MENU);
  111.     wc.lpszClassName    = WINDOW_CLASSNAME;
  112.     wc.hbrBackground    = (HBRUSH)(COLOR_BTNFACE);
  113.     if (!RegisterClass (&wc))
  114.     {
  115.         TraceMessage ("WinMain: Failed to register the application class");
  116.         return -1;
  117.     }
  118.     gpLink = new CNotifLink;
  119.     InitializeCriticalSection (&csRemoteServer);
  120.     InitializeCriticalSection (&csCancel);
  121.     
  122.     ghCancelEvent = CreateEvent (NULL, FALSE, FALSE, NULL);    
  123.  
  124.     if (!g_pctl3d)
  125.     {
  126.         BOOL f;
  127.         g_pctl3d = CTL3D_Initialize(ghInstance);
  128.         CTL3D_AutoSubclass(g_pctl3d, ghInstance, &f);
  129.     }
  130.  
  131.     InitCommonControls();
  132.  
  133.     ghWnd = CreateWindowEx (WS_EX_DLGMODALFRAME | WS_EX_APPWINDOW | WS_EX_CONTROLPARENT,
  134.                             WINDOW_CLASSNAME,
  135.                             TEXT("WINDS Administrator"),
  136.                             WS_OVERLAPPED   | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU,
  137.                             100,
  138.                             100,
  139.                             800,
  140.                             500,
  141.                             NULL,
  142.                             NULL,
  143.                             ghInstance,
  144.                             NULL);
  145.     if (NULL == ghWnd)
  146.     {
  147.         PrivateMessageBox (IDS_MSG_NO_INTERNAL_RESOURCES, NULL, 0);
  148.         goto ErrorExit;
  149.     }
  150.     hAccel = LoadAccelerators (ghInstance, MAKEINTRESOURCE (IDA_ACCELTABLE));
  151.     if (NULL == hAccel)
  152.     {
  153.         TraceMessage ("WinMain: Failed to load accelerator table");
  154.     }
  155.     
  156.     ShowWindow (ghWnd, nCmdLine);
  157.     UpdateWindow (ghWnd);
  158.  
  159.     while (GetMessage (&msg, NULL, 0, 0))
  160.     {
  161.         if (!TranslateAccelerator (msg.hwnd, hAccel, &msg))
  162.         {
  163.             TranslateMessage (&msg);
  164.             DispatchMessage (&msg);
  165.         }
  166.     }
  167. ErrorExit:
  168.  
  169.     DeleteCriticalSection (&csCancel);
  170.     DeleteCriticalSection (&csRemoteServer);
  171.     delete gpLink;
  172.     
  173.     // Free any pending RPC binding resources.
  174.     BindToServer (NULL);
  175.  
  176.     CloseHandle (ghCancelEvent);
  177.  
  178.     CTL3D_Uninitialize(g_pctl3d);
  179.     g_pctl3d = NULL;
  180.     return 0;
  181. }
  182.  
  183. ///////////////////////////////////////////////////////////////////////////////
  184. //    MainWndProc()
  185. //
  186. //    Parameters
  187. //      { Refer to Win32 API documentation on dialog procedures }
  188. //
  189. //    Purpose
  190. //      
  191. //    Return Value
  192. //      
  193. LRESULT CALLBACK MainWndProc (HWND    hWnd, 
  194.                               UINT    message, 
  195.                               WPARAM  wParam, 
  196.                               LPARAM  lParam)
  197. {
  198.     static HBRUSH hbrFace = NULL;
  199.     static HMENU hMBPopupMenu, hDLPopupMenu;
  200.     static HCURSOR hCurrentCursor = NULL;
  201.     static BOOL fRPCInProgress = FALSE;
  202.     switch (message)
  203.     {
  204.         case WM_SETCURSOR :
  205.             SetCursor (hCurrentCursor);
  206.             return TRUE;
  207.  
  208.         case WM_CREATE :
  209.             {
  210.                 hCurrentCursor = LoadCursor (NULL, IDC_ARROW);
  211.                 g_hIconImgs = ImageList_LoadBitmap (ghInstance, MAKEINTRESOURCE(IDB_ICONS), 32, 2, CLR_NONE);
  212.                 g_hImages = ImageList_LoadBitmap (ghInstance, MAKEINTRESOURCE(IDB_OBJECTS), 18, 2, CLR_NONE);
  213.                 ImageList_SetBkColor (g_hImages, GetSysColor(COLOR_WINDOW));
  214.                 
  215.                 if (!CreateListView (hWnd, g_hImages))
  216.                 {
  217.                     return -1;
  218.                 }
  219.                 if (!CreateTreeView (hWnd, g_hImages))
  220.                 {
  221.                     return -1;
  222.                 }
  223.                 if (!CreateToolBar (hWnd))
  224.                 {
  225.                     return -1;
  226.                 }
  227.                 BOOL fServerIsOnline = FALSE;
  228.                 LoadSettingsFromRegistry (g_szCurrentServer);
  229.                 if (ShowConnectDialog (hWnd, g_szCurrentServer, &fServerIsOnline) &&
  230.                     fServerIsOnline)
  231.                 {
  232.                     AddServerToList (g_szCurrentServer, TRUE);
  233.                     gpLink->StartNotification();
  234.                 }
  235.                 hbrFace = CreateSolidBrush (GetSysColor (COLOR_BTNFACE));
  236.                 ghBoldFont = CreateFont (-24,                    // Height
  237.                                          0,                      // Width
  238.                                          0,                      // Escapement
  239.                                          0,                      // Orientation
  240.                                          FW_BOLD,                // Font Weigth
  241.                                          FALSE,                  // Italic?
  242.                                          FALSE,                  // Underlined?
  243.                                          FALSE,                  // Strike out?
  244.                                          ANSI_CHARSET,           // Character set
  245.                                          OUT_STROKE_PRECIS,      // Font precision
  246.                                          CLIP_STROKE_PRECIS,     // Clip precision 
  247.                                          DRAFT_QUALITY,          // Font apperance quality
  248.                                          FF_SWISS,               // Font pitch and family,
  249.                                          TEXT("Arial"));         // Font face name
  250.                 CreateStatusBar (hWnd);
  251.  
  252.                 hMBPopupMenu = LoadMenu (ghInstance, MAKEINTRESOURCE (IDM_MAILBOX_POPUP));
  253.                 hMBPopupMenu = GetSubMenu (hMBPopupMenu, 0);
  254.  
  255.                 hDLPopupMenu = LoadMenu (ghInstance, MAKEINTRESOURCE (IDM_DISTLIST_POPUP));
  256.                 hDLPopupMenu = GetSubMenu (hDLPopupMenu, 0);
  257.  
  258.                 DWORD dwThreadID;
  259.                 HANDLE hThread = CreateThread (NULL,
  260.                                                0,
  261.                                                (LPTHREAD_START_ROUTINE)CancelThreadProc,
  262.                                                NULL,
  263.                                                0,
  264.                                                &dwThreadID);
  265.                 ASSERTMSG (hThread, "Failed to spawn cancel thread");
  266.                 TraceDebugger ("MainWndProc: RPC cancel thread spawned. ID: %X", dwThreadID);
  267.                 CloseHandle (hThread);
  268.             }
  269.             break;
  270.  
  271.         case WM_MEASUREITEM :
  272.             {
  273.                 PMEASUREITEMSTRUCT pMIS = (PMEASUREITEMSTRUCT)lParam;
  274.                 TEXTMETRIC tm;
  275.                 HDC hdc;
  276.                 HFONT hFont;
  277.                 if (pMIS->CtlType == ODT_LISTVIEW)
  278.                 {
  279.                     hFont = (HFONT)SendMessage (ghListView, WM_GETFONT, 0, 0L);
  280.                     hdc = GetDC (ghListView);
  281.                     SelectObject (hdc, hFont);
  282.                     GetTextMetrics (hdc, &tm);
  283.         
  284.                     pMIS->itemHeight = tm.tmHeight + 1;
  285.  
  286.                     if (pMIS->itemHeight < (18 + 1))
  287.                     {
  288.                         pMIS->itemHeight = 18 + 1;
  289.                     }
  290.                     ReleaseDC (ghListView, hdc);
  291.                 }
  292.             }
  293.             return TRUE;
  294.  
  295.         case WM_DRAWITEM :
  296.             {
  297.                 PDRAWITEMSTRUCT pDIS = (PDRAWITEMSTRUCT)lParam;
  298.                 if (pDIS->CtlType != ODT_LISTVIEW)
  299.                 {
  300.                     return FALSE;
  301.                 }
  302.                 switch (pDIS->itemAction)
  303.                 {
  304.                     case ODA_DRAWENTIRE:
  305.                     case ODA_FOCUS:
  306.                     case ODA_SELECT:
  307.                         DrawListViewItem (pDIS);
  308.                         break;
  309.                 }
  310.             }
  311.             return TRUE;
  312.  
  313.         case WM_PAINT :
  314.             {
  315.                 PAINTSTRUCT ps;
  316.                 RECT rc;
  317.                 GetClientRect (hWnd, &rc);
  318.                 BeginPaint (hWnd, &ps);
  319.                 FillRect (ps.hdc, &rc, hbrFace);
  320.                 EndPaint (hWnd, &ps);
  321.             }
  322.             break;
  323.  
  324.         case WM_MENUCHAR :
  325.             if (LOWORD(wParam) == 13 && 0 == HIWORD(wParam)) // 13 == RETURN
  326.             {
  327.                 PostMessage (hWnd, WM_COMMAND, IDM_FILE_PROPERTIES, 0);
  328.                 return (BOOL)1;
  329.             }
  330.             break;
  331.  
  332.         case WM_VKEYTOITEM :
  333.             if ((HWND)lParam == ghListView)
  334.             {
  335.                 if (LOWORD(wParam) == VK_DELETE)
  336.                 {
  337.                     PostMessage (hWnd, WM_COMMAND, IDM_FILE_DELETE, 0);
  338.                 }
  339.                 else
  340.                 {
  341.                     if (LOWORD(wParam) == VK_INSERT)
  342.                     {
  343.                         PostMessage (hWnd, WM_COMMAND, IDM_FILE_NEW_MAILBOX, 0);
  344.                     }
  345.                 }
  346.             }
  347.             return (BOOL)-1;
  348.  
  349.         case WM_SYSCOLORCHANGE :
  350.             SendMessage (ghListView, message, wParam, lParam);
  351.             SendMessage (ghTreeView, message, wParam, lParam);
  352.             break;
  353.  
  354.         case WM_WINDS_RESET_NOTIF_LINK :
  355.             gpLink->EndNotifications();
  356.             gpLink->StartNotification();
  357.             break;
  358.         
  359.         case WM_WINDS_UPDATEHEADERWIDTH :
  360.             UpdateHeaderWidth ((HWND)wParam, (int)lParam);
  361.             break;
  362.  
  363.         case WM_WINDS_REMOTE_CALL_IN_PROGRESS :
  364.             fRPCInProgress = TRUE;
  365.             SendMessage (ghToolBar, TB_SETSTATE, IDC_CANCEL_REMOTE_CALL, TBSTATE_ENABLED);
  366.             break;
  367.  
  368.         case WM_WINDS_REMOTE_CALL_COMPLETED :
  369.             hCurrentCursor = LoadCursor (NULL, IDC_ARROW);
  370.             SetCursor (hCurrentCursor);
  371.             SendMessage (ghStatusBar, SB_SETTEXT, 0, (LPARAM)TEXT("Ready"));
  372.             if (wParam)
  373.             {
  374.                 ErrorHandler (hWnd, (HRESULT)wParam);
  375.             }
  376.             fRPCInProgress = FALSE;
  377.             SendMessage (ghToolBar, TB_SETSTATE, IDC_CANCEL_REMOTE_CALL, TBSTATE_INDETERMINATE);
  378.             break;
  379.  
  380.         case WM_NOTIFY :
  381.             switch (((LPNMHDR)lParam)->code)
  382.             {
  383.                 case TTN_NEEDTEXT :
  384.                     // Time to display a tool tip text box. Return the ID of
  385.                     // the string in our resource table. The control will
  386.                     // pick it up from there.
  387.                     ((LPTOOLTIPTEXT)lParam)->hinst = ghInstance;
  388.                     ((LPTOOLTIPTEXT)lParam)->lpszText = (LPTSTR)((LPTOOLTIPTEXT)lParam)->hdr.idFrom;
  389.                     break;
  390.  
  391.                 case HDN_ENDTRACK:
  392.                     {
  393.                         HD_NOTIFY *phdn = (HD_NOTIFY *)lParam;
  394.                         PostMessage (hWnd,
  395.                                      WM_WINDS_UPDATEHEADERWIDTH,
  396.                                      (WPARAM)phdn->hdr.hwndFrom,
  397.                                      (LPARAM)phdn->iItem);
  398.                     }
  399.                     break;
  400.  
  401.                 case TVN_SELCHANGED :
  402.                     {
  403.                         DWORD dwThreadID;
  404.                         HANDLE hThread = NULL;
  405.                         NM_TREEVIEW * pNMTV = (NM_TREEVIEW *)lParam;
  406.                         ITEM_TYPE tvItemType = (ITEM_TYPE)pNMTV->itemNew.lParam;
  407.                         // Cancel the remote call in progress, if any
  408.                         if (fRPCInProgress)
  409.                         {
  410.                             SetEvent (ghCancelEvent);
  411.                         }
  412.                         g_LVItemsType = ITEM_UNDEFINED_TYPE;
  413.                         
  414.                         // If necessary, reset the RPC binding to the new server
  415.                         if (S_OK != ServerChanged (ghTreeView))
  416.                         {
  417.                             break;
  418.                         }
  419.  
  420.                         switch (tvItemType)
  421.                         {
  422.                             case ITEM_SERVER_USER_MAILBOXES :
  423.                                 g_LVItemsType = ITEM_SERVER_USER_MAILBOXES;
  424.                                 hThread = CreateThread (NULL,
  425.                                                         0,
  426.                                                         (LPTHREAD_START_ROUTINE)GetServerMailboxes,
  427.                                                         (LPVOID)hWnd,
  428.                                                         CREATE_SUSPENDED,
  429.                                                         &dwThreadID);
  430.                                 break;
  431.                             case ITEM_SERVER_DIST_LISTS :
  432.                                 g_LVItemsType = ITEM_SERVER_DIST_LISTS;
  433.                                 hThread = CreateThread (NULL,
  434.                                                         0,
  435.                                                         (LPTHREAD_START_ROUTINE)GetServerDistLists,
  436.                                                         (LPVOID)hWnd,
  437.                                                         CREATE_SUSPENDED,
  438.                                                         &dwThreadID);
  439.                                 break;
  440.                             default :
  441.                                 ListView_DeleteAllItems (ghListView);
  442.                                 break;
  443.                         }
  444.                         if (hThread)
  445.                         {
  446.                             hCurrentCursor = LoadCursor (NULL, IDC_APPSTARTING);
  447.                             SetCursor (hCurrentCursor);
  448.                             ResumeThread (hThread);
  449.                             CloseHandle (hThread);
  450.                             TraceDebugger ("MainWndProc: RPC worker thread spawned. ID: %X", dwThreadID);
  451.                         }
  452.                     }
  453.                     break;
  454.  
  455.                 case NM_RCLICK :
  456.                 case NM_DBLCLK :
  457.                     if (((LPNMHDR)lParam)->idFrom == IDC_LISTVIEW)
  458.                     {
  459.                         if (NM_RCLICK == ((LPNMHDR)lParam)->code)
  460.                         {
  461.                             HMENU hMenu = NULL;
  462.                             switch (g_LVItemsType)
  463.                             {
  464.                                 case ITEM_SERVER_USER_MAILBOXES :
  465.                                     hMenu = hMBPopupMenu;
  466.                                     break;
  467.                                 case ITEM_SERVER_DIST_LISTS :
  468.                                     hMenu = hDLPopupMenu;
  469.                                     break;
  470.                             }
  471.                             POINT pt;
  472.                             GetCursorPos (&pt);
  473.                             TrackPopupMenu (hMenu, 
  474.                                             TPM_CENTERALIGN | TPM_LEFTBUTTON,
  475.                                             pt.x,
  476.                                             pt.y,
  477.                                             0,
  478.                                             hWnd,
  479.                                             NULL);
  480.                         }
  481.                         else
  482.                         {
  483.                             PostMessage (hWnd, WM_COMMAND, IDM_POPUP_MB_PROPS, 0);
  484.                         }
  485.                     }
  486.                     break;
  487.             }
  488.             break;
  489.  
  490.         case WM_COMMAND :
  491.             // If a background thread is download something, we can't
  492.             // allow many things to happen.
  493.             if (fRPCInProgress && 
  494.                 IDM_ABOUT != LOWORD(wParam) &&
  495.                 IDC_CANCEL_REMOTE_CALL != LOWORD(wParam) &&
  496.                 IDM_FILE_EXIT != LOWORD(wParam))
  497.             {
  498.                 PrivateMessageBox (IDS_MSG_WAIT_FOR_COMPLETION,
  499.                                    hWnd,
  500.                                    MB_OK |
  501.                                    MB_ICONEXCLAMATION|
  502.                                    MB_SETFOREGROUND);
  503.                 break;
  504.             }
  505.             switch (LOWORD(wParam))
  506.             {
  507.                 case IDM_ABOUT :
  508.                     DialogBox (ghInstance, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, AboutDlgProc);
  509.                     break;
  510.  
  511.                 case IDM_SERVER_EXPORT :
  512.                     DialogBox (ghInstance, MAKEINTRESOURCE(IDD_EXPORT), hWnd, ExportDlgProc);
  513.                     break;
  514.  
  515.                 case IDM_SERVER_IMPORT :
  516.                     DialogBox (ghInstance, MAKEINTRESOURCE(IDD_IMPORT), hWnd, ImportDlgProc);
  517.                     break;
  518.  
  519.                 case IDC_CANCEL_REMOTE_CALL :
  520.                     SetEvent (ghCancelEvent);
  521.                     break;
  522.  
  523.                 case IDM_FILE_PROPERTIES :
  524.                 case IDM_FILE_DELETE :
  525.                 case IDM_POPUP_MB_PROPS :
  526.                 case IDM_POPUP_MB_EMPTY :
  527.                 case IDM_POPUP_MB_HEADERS :
  528.                 case IDM_POPUP_MB_DELETE :
  529.                     {
  530.                         int nItem = ListView_GetNextItem (ghListView, -1, LVNI_FOCUSED | LVNI_ALL);
  531.                         if (-1 == nItem)
  532.                         {
  533.                             break;
  534.                         }
  535.                         HandleItemAction (hWnd, nItem, LOWORD(wParam));
  536.                     }
  537.                     break;
  538.  
  539.                 case IDM_FIND_MAILBOX :
  540.                     break;
  541.  
  542.                 case IDM_FILE_NEW_MAILBOX :
  543.                     CreateNewMailbox (hWnd);
  544.                     break;
  545.  
  546.                 case IDM_FILE_NEW_DISTRIBUTIONLIST :
  547.                     CreateNewDistList (hWnd);
  548.                     break;
  549.  
  550.                 case IDM_VIEW_DISCONNECT :
  551.                     DialogBox (ghInstance, MAKEINTRESOURCE(IDD_REMOVE_SERVER), hWnd, RemoveServersDlgProc);
  552.                     break;
  553.  
  554.                 case IDM_VIEW_CONNECT :
  555.                     {
  556.                         TCHAR szNewServer[64] = { 0 };
  557.                         BOOL fServerIsOnline = FALSE;
  558.                         if (ShowConnectDialog (hWnd, szNewServer, &fServerIsOnline) &&
  559.                             fServerIsOnline)
  560.                         {
  561.                             AddServerToList (szNewServer, (NULL == g_szCurrentServer[0] ? TRUE : FALSE));
  562.                             if (NULL == g_szCurrentServer[0])
  563.                             {
  564.                                 lstrcpy (g_szCurrentServer, szNewServer);
  565.                             }
  566.                         }
  567.                     }
  568.                     break;
  569.  
  570.                 case IDM_FILE_EXIT :
  571.                     // Terminate the application
  572.                     PostMessage (hWnd, WM_CLOSE, 0, 0);
  573.                     break;
  574.             }
  575.             break;
  576.  
  577.         case WM_QUERYENDSESSION :
  578.         case WM_DESTROY :
  579.             gfTerminate = TRUE;
  580.             SetEvent (ghCancelEvent);
  581.             
  582.             DeleteObject (hbrFace);
  583.             DeleteObject (ghBoldFont);
  584.             ImageList_Destroy (g_hImages);
  585.             ImageList_Destroy (g_hIconImgs);
  586.             DestroyWindow (ghListView);
  587.             DestroyWindow (ghTreeView);
  588.             DestroyWindow (ghStatusBar);
  589.             DestroyWindow (ghToolBar);
  590.             DestroyMenu (hMBPopupMenu);
  591.             DestroyMenu (hDLPopupMenu);
  592.             PostQuitMessage (0);
  593.             break;
  594.  
  595.         default :
  596.             return DefWindowProc (hWnd, message, wParam, lParam);
  597.     }
  598.     return 0;
  599. }
  600.  
  601. ///////////////////////////////////////////////////////////////////////////////
  602. //    HandleItemAction()
  603. //
  604. //    Parameters
  605. //
  606. //    Purpose
  607. //      
  608. //    Return Value
  609. //      
  610. void WINAPI HandleItemAction (HWND hOwnerWnd, int nItem, WORD wAction)
  611. {
  612.     LV_ITEM lvi = { 0 };
  613.     lvi.mask = LVIF_PARAM;
  614.     lvi.iItem = nItem;
  615.     lvi.iSubItem = 0;
  616.     if (FALSE == ListView_GetItem (ghListView, &lvi))
  617.     {
  618.         return;
  619.     }
  620.     switch (wAction)
  621.     {
  622.         case IDM_FILE_PROPERTIES :
  623.         case IDM_POPUP_MB_PROPS :
  624.             switch (g_LVItemsType)
  625.             {
  626.                 case ITEM_SERVER_USER_MAILBOXES :
  627.                     ShowMailboxProps (hOwnerWnd, lvi.lParam);
  628.                     break;
  629.                 case ITEM_SERVER_DIST_LISTS :
  630.                     ShowDistListProps (hOwnerWnd, lvi.lParam);
  631.                     break;
  632.                 case ITEM_SERVER_FOREIGN_MAILBOXES :
  633.                     TraceMessage ("Properties of Foreign Recipient");
  634.                     break;
  635.                 case ITEM_SERVER_PUBLIC_FOLDERS :
  636.                     TraceMessage ("Properties of public folder");
  637.                     break;
  638.                 case ITEM_SERVER_GATEWAYS :
  639.                     TraceMessage ("Properties of Server gateway");
  640.                     break;
  641.             }
  642.             break;
  643.  
  644.         case IDM_POPUP_MB_EMPTY :
  645.             if (ITEM_SERVER_USER_MAILBOXES == g_LVItemsType)
  646.             {
  647.                 PurgeMailboxMessages (hOwnerWnd, lvi.lParam);
  648.             }
  649.             break;
  650.  
  651.         case IDM_FILE_DELETE :
  652.         case IDM_POPUP_MB_DELETE :
  653.             switch (g_LVItemsType)
  654.             {
  655.                 case ITEM_SERVER_USER_MAILBOXES :
  656.                 case ITEM_SERVER_DIST_LISTS :
  657.                     DeleteServerObject (hOwnerWnd, lvi.lParam);
  658.                     break;
  659.                 case ITEM_SERVER_FOREIGN_MAILBOXES :
  660.                     TraceMessage ("Delete Foreign Recipient");
  661.                     break;
  662.                 case ITEM_SERVER_PUBLIC_FOLDERS :
  663.                     TraceMessage ("Delete Public folder");
  664.                     break;
  665.             }
  666.             break;
  667.  
  668.         case IDM_POPUP_MB_HEADERS :
  669.             TraceMessage ("View mailbox headers");
  670.             break;
  671.     }
  672. }
  673.  
  674. ///////////////////////////////////////////////////////////////////////////////
  675. //    AboutDlgProc()
  676. //
  677. //    Parameters
  678. //      { Refer to Win32 API documentation on dialog procedures }
  679. //
  680. //    Purpose
  681. //      Displays a dialog box with the copyright and program information
  682. //      
  683. //    Return Value
  684. //      TRUE if message was handled, FALSE if we don't handle the message
  685. //      
  686. BOOL CALLBACK AboutDlgProc (HWND    hDlg, 
  687.                             UINT    message, 
  688.                             WPARAM  wParam, 
  689.                             LPARAM  lParam)
  690. {
  691.     if (WM_INITDIALOG == message)
  692.     {
  693.         CenterDialogBox (hDlg);
  694.         return TRUE;
  695.     }
  696.     else
  697.     {
  698.         if (WM_COMMAND == message && (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL))
  699.         {   
  700.             EndDialog (hDlg, TRUE);
  701.             return TRUE;
  702.         }
  703.     }
  704.     return FALSE;
  705. }
  706.  
  707. ///////////////////////////////////////////////////////////////////////////////
  708. //    AddServerToList()
  709. //
  710. //    Parameters
  711. //
  712. //    Purpose
  713. //
  714. //    Return Value
  715. //
  716. void WINAPI AddServerToList (LPTSTR szServer, BOOL fExpandRoot)
  717. {
  718.     HTREEITEM hItem, hRoot;
  719.     TV_INSERTSTRUCT tvIns = { 0 };
  720.     TV_ITEM tvItem = 
  721.     {
  722.         TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM,
  723.         NULL,
  724.         0,
  725.         0,
  726.         NULL,
  727.         0,
  728.         IMG_SERVER,
  729.         IMG_SERVER,
  730.         0,
  731.         NULL
  732.     };
  733.     TCHAR szName[128];
  734.  
  735.     // Add the root item
  736.     wsprintf (szName, TEXT("WINDS Server: %s"), szServer);
  737.     tvItem.pszText = szName,
  738.     tvIns.hParent = NULL;
  739.     tvItem.lParam = (LPARAM)ITEM_REMOTE_SERVER;
  740.     tvIns.item    = tvItem;
  741.     hRoot = TreeView_InsertItem (ghTreeView, &tvIns);
  742.  
  743.     // Add the "Object Directory" item
  744.     tvItem.pszText = TEXT("Object Directory");
  745.     tvItem.iImage = IMG_MAILABLE_OBJECTS_CLOSE;
  746.     tvItem.iSelectedImage = IMG_MAILABLE_OBJECTS_OPEN;
  747.     tvItem.lParam = (LPARAM)ITEM_OBJECT_DIRECTORY;
  748.     tvIns.hParent = hRoot;
  749.     tvIns.item    = tvItem;
  750.     hItem = TreeView_InsertItem (ghTreeView, &tvIns);
  751.  
  752.     // Add the "User Mailboxes" item
  753.     tvItem.pszText = TEXT("User Mailboxes");
  754.     tvItem.iImage = IMG_USER;
  755.     tvItem.iSelectedImage = IMG_USER;
  756.     tvItem.lParam  = (LPARAM)ITEM_SERVER_USER_MAILBOXES;
  757.     tvIns.hParent = hItem;
  758.     tvIns.item    = tvItem;
  759.     TreeView_InsertItem (ghTreeView, &tvIns);
  760.  
  761.     // Add the "Server DLs" item
  762.     tvItem.pszText = TEXT("Server Distribution Lists");
  763.     tvItem.iImage = IMG_MAIL_GROUP;
  764.     tvItem.iSelectedImage = IMG_MAIL_GROUP;
  765.     tvItem.lParam  = (LPARAM)ITEM_SERVER_DIST_LISTS;
  766.     tvIns.hParent = hItem;
  767.     tvIns.item = tvItem;
  768.     TreeView_InsertItem (ghTreeView, &tvIns);
  769.  
  770.     // Add the "Foreign Entries" item
  771.     tvItem.pszText = TEXT("Foreign Mailboxes");
  772.     tvItem.iImage = IMG_FOREIGN_USER;
  773.     tvItem.iSelectedImage = IMG_FOREIGN_USER;
  774.     tvItem.lParam = (LPARAM)ITEM_SERVER_FOREIGN_MAILBOXES;
  775.     tvItem.lParam = NULL;
  776.     tvIns.hParent = hItem;
  777.     tvIns.item = tvItem;
  778.     TreeView_InsertItem (ghTreeView, &tvIns);
  779.  
  780.     TreeView_Expand (ghTreeView, hItem, TVE_EXPAND);
  781.  
  782.     tvItem.pszText = TEXT("Public Folders");
  783.     tvItem.iImage = IMG_SERVER_PUB_FOLDER;
  784.     tvItem.iSelectedImage = IMG_SERVER_PUB_FOLDER;
  785.     tvItem.lParam = (LPARAM)ITEM_SERVER_PUBLIC_FOLDERS;
  786.     tvIns.hParent = hRoot;
  787.     tvIns.item = tvItem;
  788.     TreeView_InsertItem (ghTreeView, &tvIns);
  789.  
  790.     tvItem.pszText = TEXT("Gateways");
  791.     tvItem.iImage = IMG_SERVER_GATEWAY;
  792.     tvItem.iSelectedImage = IMG_SERVER_GATEWAY;
  793.     tvItem.lParam = (LPARAM)ITEM_SERVER_GATEWAYS;
  794.     tvIns.hParent = hRoot;
  795.     tvIns.item = tvItem;
  796.     hItem = TreeView_InsertItem (ghTreeView, &tvIns);
  797.  
  798.     tvItem.pszText = TEXT("Exchange Gateway");
  799.     tvItem.iImage = IMG_GATEWAY;
  800.     tvItem.iSelectedImage = IMG_GATEWAY;
  801.     tvItem.lParam = (LPARAM)ITEM_SERVER_GATEWAYS;
  802.     tvIns.hParent = hItem;
  803.     tvIns.item = tvItem;
  804.     TreeView_InsertItem (ghTreeView, &tvIns);
  805.  
  806.     tvItem.pszText = TEXT("SMTP Gateway");
  807.     tvItem.iImage = IMG_GATEWAY;
  808.     tvItem.iSelectedImage = IMG_GATEWAY;
  809.     tvItem.lParam = (LPARAM)ITEM_SERVER_GATEWAYS;
  810.     tvIns.hParent = hItem;
  811.     tvIns.item = tvItem;
  812.     TreeView_InsertItem (ghTreeView, &tvIns);
  813.  
  814.     tvItem.pszText = TEXT("FAX Gateway");
  815.     tvItem.iImage = IMG_GATEWAY;
  816.     tvItem.iSelectedImage = IMG_GATEWAY;
  817.     tvItem.lParam = (LPARAM)ITEM_SERVER_GATEWAYS;
  818.     tvIns.hParent = hItem;
  819.     tvIns.item = tvItem;
  820.     TreeView_InsertItem (ghTreeView, &tvIns);
  821.  
  822.     TreeView_Expand (ghTreeView, hItem, TVE_EXPAND);
  823.  
  824.     if (fExpandRoot)
  825.     {
  826.         TreeView_Expand (ghTreeView, hRoot, TVE_EXPAND);
  827.     }
  828. }
  829.  
  830. ///////////////////////////////////////////////////////////////////////////////
  831. //    CancelThreadProc()
  832. //
  833. //    Parameters
  834. //
  835. //    Purpose
  836. //
  837. //    Return Value
  838. //
  839. HRESULT WINAPI CancelThreadProc()
  840. {
  841.     while (TRUE)
  842.     {
  843.         WaitForSingleObject (ghCancelEvent, INFINITE);
  844.         if (gfTerminate)
  845.         {
  846.             break; // Out of the WHILE() loop
  847.         }
  848.         EnterCriticalSection (&csCancel);
  849.         gfCancel = TRUE;
  850.         LeaveCriticalSection (&csCancel);
  851.     }
  852.     return S_OK;
  853. }
  854.  
  855. ///////////////////////////////////////////////////////////////////////////////
  856. //    LoadSettingsFromRegistry()
  857. //
  858. //    Parameters
  859. //      
  860. //    Purpose
  861. //      
  862. //    Return Value
  863. //      None
  864. //      
  865. void WINAPI LoadSettingsFromRegistry (LPTSTR szServer)
  866. {
  867.     HKEY hAppKey;
  868.     // Try to open the key in the registry, open it with READ rights,
  869.     // and read the data into our strcture
  870.     if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_CURRENT_USER,
  871.                                        WINDS_ADMIN_REGISTRY_KEY,
  872.                                        0,
  873.                                        KEY_READ,
  874.                                        &hAppKey))
  875.     {
  876.         ULONG cbSize = 64;
  877.         DWORD dwError = RegQueryValueEx (hAppKey,
  878.                                          SERVER_SUB_KEY,
  879.                                          NULL,
  880.                                          NULL,
  881.                                          (LPBYTE)szServer,
  882.                                          &cbSize);
  883.         RegCloseKey (hAppKey);
  884.         // If we failed to get the data from the registry we can't return
  885.         // yet, we will proceed to initialize the options with default
  886.         // values
  887.         if (ERROR_SUCCESS == dwError)
  888.         {
  889.             return;
  890.         }
  891.     }
  892. }
  893.  
  894. ///////////////////////////////////////////////////////////////////////////////
  895. //    SaveSettingsToRegistry()
  896. //
  897. //    Parameters
  898. //
  899. //    Purpose
  900. //      
  901. //    Return Value
  902. //      None
  903. //      
  904. void WINAPI SaveSettingsToRegistry (LPTSTR szServer)
  905. {
  906.     HKEY hAppKey;
  907.     DWORD dwDisposition;
  908.     // Try to open the key in the registry, open it with READ/WRITE rights
  909.     if (ERROR_SUCCESS != RegCreateKeyEx (HKEY_CURRENT_USER,
  910.                                          WINDS_ADMIN_REGISTRY_KEY,
  911.                                          0,
  912.                                          NULL,
  913.                                          REG_OPTION_NON_VOLATILE,
  914.                                          KEY_WRITE,
  915.                                          NULL,
  916.                                          &hAppKey,
  917.                                          &dwDisposition))
  918.     {
  919.         // If we fail to access the registry, we need to get out, we don't
  920.         // have a key opened where to write
  921.         TraceResult ("SaveSettingsToRegistry: Failed to open app key", HRESULT_FROM_WIN32(GetLastError()));
  922.     }
  923.     else
  924.     {
  925.         // With the opened key handle, create a sub entry where we save our
  926.         // structure values. For this sample we just write the entire
  927.         // structure as a big blob of data, which we read the save way.
  928.         if (ERROR_SUCCESS != RegSetValueEx (hAppKey,
  929.                                             SERVER_SUB_KEY,
  930.                                             0,
  931.                                             REG_SZ,
  932.                                             (LPBYTE)szServer,
  933.                                             (1+lstrlen(szServer))*sizeof(TCHAR)))
  934.         {
  935.             TraceResult ("SaveSettingsToRegistry: Failed to save registry values", HRESULT_FROM_WIN32(GetLastError()));
  936.         }
  937.         // Close the handle we have open and return the appropiate flag
  938.         RegCloseKey (hAppKey);
  939.     }
  940. }
  941.  
  942. ///////////////////////////////////////////////////////////////////////////////
  943. //    ShowConnectDialog()
  944. //
  945. //    Parameters
  946. //
  947. //    Purpose
  948. //      
  949. //    Return Value
  950. //      None
  951. //      
  952. BOOL WINAPI ShowConnectDialog (HWND hOwnerWnd, LPTSTR szServer, BOOL * pfServerIsOnLine)
  953. {
  954.     *pfServerIsOnLine = FALSE;
  955.     BOOL bResult = FALSE;
  956.     if (lstrlen(szServer))
  957.     {
  958.         goto ConnectToServer;
  959.     }
  960. ReEnterServerName:
  961.     // Free any previous bindings
  962.     BindToServer (NULL);
  963.     SetCursor (LoadCursor (NULL, IDC_ARROW));
  964.     if (TRUE == DialogBoxParam (ghInstance,
  965.                                 MAKEINTRESOURCE(IDD_SERVER_CONNECT),
  966.                                 hOwnerWnd,
  967.                                 ServerConnectDlgProc,
  968.                                 (LPARAM)szServer))
  969.     {
  970. ConnectToServer:
  971.         SetCursor (LoadCursor (NULL, IDC_WAIT));
  972.         HRESULT hResult = BindToServer (szServer);
  973.         if (!hResult)
  974.         {
  975.             RpcTryExcept
  976.             {
  977.                 hResult = RemoteAdmIsServerRunning();
  978.                 if (!hResult)
  979.                 {
  980.                     *pfServerIsOnLine = TRUE;
  981.                 }
  982.             }
  983.             RpcExcept(1)
  984.             {        
  985.                 // If we got here is because there was an error while call was made
  986.                 // or when it was about to be made.
  987.                 hResult = RpcExceptionCode();
  988.                 if (RPC_S_SERVER_UNAVAILABLE == hResult)
  989.                 {
  990.                     hResult = HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE);
  991.                 }
  992.                 else
  993.                 {
  994.                     hResult = MAKE_HRESULT(1, FACILITY_RPC, hResult);
  995.                 }
  996.             }
  997.             RpcEndExcept
  998.             switch (hResult)
  999.             {
  1000.                 case S_OK :
  1001.                     break;
  1002.                 case HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE) :
  1003.                     SetCursor (LoadCursor (NULL, IDC_ARROW));
  1004.                     if (IDYES == PrivateMessageBox (IDS_MSG_SERVER_NOT_FOUND,
  1005.                                                     hOwnerWnd,
  1006.                                                     MB_YESNO |
  1007.                                                     MB_ICONSTOP |
  1008.                                                     MB_SETFOREGROUND))
  1009.                     {
  1010.                         goto ReEnterServerName;
  1011.                     }
  1012.                     break;
  1013.                 default :
  1014.                     TraceResult ("ShowConnectDialog", hResult);
  1015.                     goto ReEnterServerName;
  1016.                     break;
  1017.             }
  1018.             bResult = TRUE;
  1019.         }
  1020.     }
  1021.     SetCursor (LoadCursor (NULL, IDC_ARROW));
  1022.     BindToServer (g_szCurrentServer);
  1023.     return bResult;
  1024. }
  1025.  
  1026. ///////////////////////////////////////////////////////////////////////////////
  1027. //    ServerConnectDlgProc()
  1028. //
  1029. //    Parameters
  1030. //      { Refer to Win32 API documentation on dialog procedures }
  1031. //
  1032. //    Purpose
  1033. //      
  1034. //    Return Value
  1035. //      TRUE if message was handled, FALSE if we don't handle the message
  1036. //      
  1037. BOOL CALLBACK ServerConnectDlgProc (HWND    hDlg, 
  1038.                                     UINT    message, 
  1039.                                     WPARAM  wParam, 
  1040.                                     LPARAM  lParam)
  1041. {
  1042.     static LPTSTR szServer;
  1043.     switch (message)
  1044.     {
  1045.         case WM_INITDIALOG :
  1046.             szServer = (LPTSTR)lParam;
  1047.             CenterDialogBox (hDlg);
  1048.             Edit_LimitText (GetDlgItem (hDlg, IDC_SERVER_NAME), 32);
  1049.             SetFocus (GetDlgItem (hDlg, IDC_SERVER_NAME));
  1050.             if (NULL == g_szCurrentServer[0])
  1051.             {
  1052.                 Button_SetCheck (GetDlgItem (hDlg, IDC_SERVER_DEFAULT), BST_CHECKED);
  1053.             }
  1054.             Static_SetIcon (GetDlgItem (hDlg, IDC_PAGE_ICON),
  1055.                             ImageList_GetIcon (g_hIconImgs, ICON_CONNECT, ILD_NORMAL));
  1056.             return TRUE;
  1057.  
  1058.         case WM_COMMAND :
  1059.             switch (LOWORD(wParam))
  1060.             {
  1061.                 case IDOK :
  1062.                     if (GetWindowText (GetDlgItem (hDlg, IDC_SERVER_NAME), szServer, 64))
  1063.                     {
  1064.                         if (FALSE == IsValidServerName (szServer))
  1065.                         {
  1066.                             PrivateMessageBox (IDS_MSG_INVALID_SERVER_NAME, hDlg, 0);
  1067.                             return TRUE;
  1068.                         }
  1069.                         BOOL fDuplicate = FALSE;
  1070.                         TCHAR szBuffer[128], *szConnectedServer;
  1071.                         TV_ITEM tvItem = { 0 };
  1072.                         tvItem.mask = TVIF_TEXT;
  1073.                         tvItem.pszText = szBuffer;
  1074.                         tvItem.cchTextMax = 128;
  1075.                         HTREEITEM hItem = TreeView_GetRoot (ghTreeView);
  1076.                         while (hItem)
  1077.                         {
  1078.                             tvItem.hItem = hItem;
  1079.                             if (TRUE == TreeView_GetItem (ghTreeView, &tvItem))
  1080.                             {
  1081.                                 GetServerNameFromTitle (szBuffer, &szConnectedServer);
  1082.                                 if (0 == lstrcmpi(szServer, szConnectedServer))
  1083.                                 {
  1084.                                     fDuplicate = TRUE;
  1085.                                     break; // Out of the WHILE() loop
  1086.                                 }
  1087.                             }
  1088.                             hItem = TreeView_GetNextItem (ghTreeView, hItem, TVGN_NEXT);
  1089.                         }
  1090.                         if (fDuplicate)
  1091.                         {
  1092.                             wParam = IDCANCEL;
  1093.                         }
  1094.                         else
  1095.                         {
  1096.                             if (BST_CHECKED == Button_GetCheck (GetDlgItem (hDlg, IDC_SERVER_DEFAULT)))
  1097.                             {
  1098.                                 SaveSettingsToRegistry (szServer);
  1099.                             }
  1100.                         }
  1101.                     }
  1102.                     else
  1103.                     {
  1104.                         return TRUE;
  1105.                     }
  1106.                     // fall through
  1107.                 case IDCANCEL :
  1108.                     EndDialog (hDlg, (LOWORD(wParam) == IDOK ? TRUE : FALSE));
  1109.                     return TRUE;
  1110.             }
  1111.     }
  1112.     return FALSE;
  1113. }
  1114.  
  1115. ///////////////////////////////////////////////////////////////////////////////
  1116. //    IsValidServerName()
  1117. //
  1118. //    Parameters
  1119. //      pszServerName       Pointer to a string with the UNC name of a
  1120. //                          network or local server
  1121. //    Purpose
  1122. //      Check the string for a server name and determines if the name is a
  1123. //      valid UNC name for a network server
  1124. //
  1125. //    Return Value
  1126. //      TRUE if the server name is valid, FALSE otherwise.
  1127. //      
  1128. BOOL WINAPI IsValidServerName (LPTSTR pszServerName)
  1129. {
  1130.     // Server name need to be at least "\\x"
  1131.     if (lstrlen(pszServerName) < 3)
  1132.     {
  1133.         return FALSE;
  1134.     }
  1135.     // The first two character in the string must be "\". This is standard
  1136.     // UNC (Universal Naming Convention) for server names
  1137.     if (pszServerName[0] != '\\' || pszServerName[1] != '\\')
  1138.     {
  1139.         return FALSE;
  1140.     }
  1141.     return TRUE;
  1142. }
  1143.  
  1144. ///////////////////////////////////////////////////////////////////////////////
  1145. //    RemoveServersDlgProc()
  1146. //
  1147. //    Parameters
  1148. //      { Refer to Win32 API documentation on dialog procedures }
  1149. //
  1150. //    Purpose
  1151. //      
  1152. //    Return Value
  1153. //      TRUE if message was handled, FALSE if we don't handle the message
  1154. //      
  1155. BOOL CALLBACK RemoveServersDlgProc (HWND    hDlg, 
  1156.                                     UINT    message, 
  1157.                                     WPARAM  wParam, 
  1158.                                     LPARAM  lParam)
  1159. {
  1160.     switch (message)
  1161.     {
  1162.         case WM_INITDIALOG :
  1163.             {
  1164.                 CenterDialogBox (hDlg);
  1165.                 CTL3D_Subclass(g_pctl3d, hDlg, CTL3D_ALL);
  1166.                 HWND hListView = GetDlgItem (hDlg, IDC_SERVER_LIST);
  1167.                 ListView_SetImageList (hListView, g_hImages, LVSIL_SMALL);
  1168.                 RECT rc;
  1169.                 GetClientRect (hListView, &rc);
  1170.                 LV_COLUMN lvc = { 0 };
  1171.                 lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  1172.                 lvc.fmt = LVCFMT_LEFT;
  1173.                 lvc.pszText = TEXT("Server Name");
  1174.                 lvc.cx = rc.right - rc.left;
  1175.                 ListView_InsertColumn (hListView, 0, &lvc);
  1176.  
  1177.                 TCHAR szBuffer[128];
  1178.  
  1179.                 LV_ITEM lvi = { 0 };
  1180.                 lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  1181.                 lvi.iImage = IMG_SERVER;
  1182.                 
  1183.                 TV_ITEM tvItem = { 0 };
  1184.                 tvItem.mask = TVIF_TEXT;
  1185.                 tvItem.pszText = szBuffer;
  1186.                 tvItem.cchTextMax = 128;
  1187.                 HTREEITEM hItem = TreeView_GetRoot (ghTreeView);
  1188.                 while (hItem)
  1189.                 {
  1190.                     tvItem.hItem = hItem;
  1191.                     if (TRUE == TreeView_GetItem (ghTreeView, &tvItem))
  1192.                     {
  1193.                         GetServerNameFromTitle (szBuffer, &lvi.pszText);
  1194.                         lvi.lParam = (LPARAM)hItem;
  1195.                         ListView_InsertItem (hListView, &lvi);
  1196.                         lvi.iItem++;
  1197.                     }
  1198.                     hItem = TreeView_GetNextItem (ghTreeView, hItem, TVGN_NEXT);
  1199.                 }
  1200.             }
  1201.             return TRUE;
  1202.  
  1203.         case WM_COMMAND :
  1204.             switch (LOWORD(wParam))
  1205.             {
  1206.                 case IDOK :
  1207.                     {
  1208.                         HWND hListView = GetDlgItem (hDlg, IDC_SERVER_LIST);
  1209.                         TCHAR szBuffer[128];
  1210.                         BOOL fSuccess;
  1211.                         LV_ITEM lvi = { 0 };
  1212.                         lvi.mask = LVIF_TEXT | LVIF_PARAM;
  1213.                         lvi.pszText = szBuffer;
  1214.                         lvi.cchTextMax = 128;
  1215.                         lvi.iItem = ListView_GetNextItem (hListView, -1, LVNI_SELECTED);
  1216.                         while (-1 != lvi.iItem)
  1217.                         {
  1218.                             if (TRUE == ListView_GetItem (hListView, &lvi))
  1219.                             {
  1220.                                 fSuccess = TreeView_DeleteItem (ghTreeView, (HTREEITEM)lvi.lParam);
  1221.                                 if (fSuccess && 0 == lstrcmpi (g_szCurrentServer, szBuffer))
  1222.                                 {
  1223.                                     gpLink->EndNotifications();
  1224.                                     BindToServer (NULL);
  1225.                                     ZeroMemory (g_szCurrentServer, sizeof(g_szCurrentServer));
  1226.                                     ListView_DeleteAllItems (ghListView);
  1227.                                 }
  1228.                             }
  1229.                             lvi.iItem = ListView_GetNextItem (hListView, lvi.iItem, LVNI_SELECTED);
  1230.                         }
  1231.                     }
  1232.                     // fall through
  1233.                 case IDCANCEL :
  1234.                     ListView_SetImageList (GetDlgItem (hDlg, IDC_SERVER_LIST), NULL, LVSIL_SMALL);
  1235.                     EndDialog (hDlg, (LOWORD(wParam) == IDOK ? TRUE : FALSE));
  1236.                     return TRUE;
  1237.             }
  1238.     }
  1239.     return FALSE;
  1240. }
  1241.  
  1242. ///////////////////////////////////////////////////////////////////////////////
  1243. //    GetServerNameFromTitle()
  1244. //
  1245. //    Parameters
  1246. //
  1247. //    Purpose
  1248. //      
  1249. //    Return Value
  1250. //      
  1251. void WINAPI GetServerNameFromTitle (LPTSTR szItemTitle, LPTSTR * pszServerName)
  1252. {
  1253.     LPTSTR pStr = &(szItemTitle[lstrlen (szItemTitle)]);
  1254.     while ('\\' != *pStr)
  1255.     {
  1256.         pStr--;
  1257.     }
  1258.     pStr--;
  1259.     *pszServerName = pStr;
  1260. }
  1261.  
  1262. ///////////////////////////////////////////////////////////////////////////////
  1263. //    ServerChanged()
  1264. //
  1265. //    Parameters
  1266. //
  1267. //    Purpose
  1268. //      
  1269. //    Return Value
  1270. //      
  1271. HRESULT WINAPI ServerChanged (HWND hTreeView)
  1272. {
  1273.     HTREEITEM hParent, hItem = TreeView_GetSelection (hTreeView);
  1274.     do
  1275.     {
  1276.         hParent = TreeView_GetParent (hTreeView, hItem);
  1277.         if (hParent)
  1278.         {
  1279.             hItem = hParent;
  1280.         }
  1281.     } while (hParent);
  1282.     
  1283.     LPTSTR szServerName;
  1284.     HRESULT hResult = S_OK;;
  1285.     TCHAR szBuffer[128];
  1286.     TV_ITEM tvItem = { 0 };
  1287.     tvItem.mask = TVIF_TEXT;
  1288.     tvItem.pszText = szBuffer;
  1289.     tvItem.cchTextMax = 128;
  1290.     tvItem.hItem = hItem;
  1291.     if (TRUE == TreeView_GetItem (hTreeView, &tvItem))
  1292.     {
  1293.         GetServerNameFromTitle (szBuffer, &szServerName);
  1294.         if (szServerName && lstrcmpi (g_szCurrentServer, szServerName) && szServerName[0])
  1295.         {
  1296.             // Terminate the notifications with the current selected server
  1297.             gpLink->EndNotifications();
  1298.             // Release the RPC binding resources
  1299.             BindToServer (NULL);
  1300.             // Copy the server name to the global buffer
  1301.             lstrcpy (g_szCurrentServer, szServerName);
  1302.             // Set the RPC binding resources to point to the new server
  1303.             BindToServer (g_szCurrentServer);
  1304.             // Establish notification with the new server we are talking to
  1305.             gpLink->StartNotification();
  1306.         }
  1307.     }
  1308.     else
  1309.     {
  1310.         hResult = E_FAIL;
  1311.     }
  1312.     return hResult;
  1313. }
  1314.  
  1315. // End of file for ADMIN.CPP
  1316.