1 /*
2  *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
3  *
4  *Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  *"Software"), to deal in the Software without restriction, including
7  *without limitation the rights to use, copy, modify, merge, publish,
8  *distribute, sublicense, and/or sell copies of the Software, and to
9  *permit persons to whom the Software is furnished to do so, subject to
10  *the following conditions:
11  *
12  *The above copyright notice and this permission notice shall be
13  *included in all copies or substantial portions of the Software.
14  *
15  *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
19  *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20  *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21  *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  *
23  *Except as contained in this notice, the name of Harold L Hunt II
24  *shall not be used in advertising or otherwise to promote the sale, use
25  *or other dealings in this Software without prior written authorization
26  *from Harold L Hunt II.
27  *
28  * Authors:	Harold L Hunt II
29  *              Earle F. Philhower III
30  */
31 
32 #ifdef HAVE_XWIN_CONFIG_H
33 #include <xwin-config.h>
34 #endif
35 #include "win.h"
36 #include <shellapi.h>
37 #include "winprefs.h"
38 
39 /*
40  * Local function prototypes
41  */
42 
43 static INT_PTR CALLBACK
44 winExitDlgProc(HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam);
45 
46 static INT_PTR CALLBACK
47 winChangeDepthDlgProc(HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam);
48 
49 static INT_PTR CALLBACK
50 winAboutDlgProc(HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam);
51 
52 static void
53  winDrawURLWindow(LPARAM lParam);
54 
55 static LRESULT CALLBACK
56 winURLWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
57 
58 static void
59  winOverrideURLButton(HWND hdlg, int id);
60 
61 static void
62  winUnoverrideURLButton(HWND hdlg, int id);
63 
64 /*
65  * Owner-draw a button as a URL
66  */
67 
68 static void
winDrawURLWindow(LPARAM lParam)69 winDrawURLWindow(LPARAM lParam)
70 {
71     DRAWITEMSTRUCT *draw;
72     char str[256];
73     RECT rect;
74     HFONT font;
75     COLORREF crText;
76 
77     draw = (DRAWITEMSTRUCT *) lParam;
78     GetWindowText(draw->hwndItem, str, sizeof(str));
79     str[255] = 0;
80     GetClientRect(draw->hwndItem, &rect);
81 
82     /* Color the button depending upon its state */
83     if (draw->itemState & ODS_SELECTED)
84         crText = RGB(128 + 64, 0, 0);
85     else if (draw->itemState & ODS_FOCUS)
86         crText = RGB(0, 128 + 64, 0);
87     else
88         crText = RGB(0, 0, 128 + 64);
89     SetTextColor(draw->hDC, crText);
90 
91     /* Create font 8 high, standard dialog font */
92     font = CreateFont(-8, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
93                       0, 0, 0, 0, 0, "MS Sans Serif");
94     if (!font) {
95         ErrorF("winDrawURLWindow: Unable to create URL font, bailing.\n");
96         return;
97     }
98     /* Draw it */
99     SetBkMode(draw->hDC, OPAQUE);
100     SelectObject(draw->hDC, font);
101     DrawText(draw->hDC, str, strlen(str), &rect, DT_LEFT | DT_VCENTER);
102     /* Delete the created font, replace it with stock font */
103     DeleteObject(SelectObject(draw->hDC, GetStockObject(ANSI_VAR_FONT)));
104 }
105 
106 /*
107  * WndProc for overridden buttons
108  */
109 
110 static LRESULT CALLBACK
winURLWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)111 winURLWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
112 {
113     WNDPROC origCB = NULL;
114     HCURSOR cursor;
115 
116     /* If it's a SetCursor message, tell it to the hand */
117     if (msg == WM_SETCURSOR) {
118         cursor = LoadCursor(NULL, IDC_HAND);
119         if (cursor)
120             SetCursor(cursor);
121         return TRUE;
122     }
123     origCB = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_USERDATA);
124     /* Otherwise fall through to original WndProc */
125     if (origCB)
126         return CallWindowProc(origCB, hwnd, msg, wParam, lParam);
127     else
128         return FALSE;
129 }
130 
131 /*
132  * Register and unregister the custom WndProc
133  */
134 
135 static void
winOverrideURLButton(HWND hwnd,int id)136 winOverrideURLButton(HWND hwnd, int id)
137 {
138     WNDPROC origCB;
139 
140     origCB = (WNDPROC) SetWindowLongPtr(GetDlgItem(hwnd, id),
141                                         GWLP_WNDPROC, (LONG_PTR) winURLWndProc);
142     SetWindowLongPtr(GetDlgItem(hwnd, id), GWLP_USERDATA, (LONG_PTR) origCB);
143 }
144 
145 static void
winUnoverrideURLButton(HWND hwnd,int id)146 winUnoverrideURLButton(HWND hwnd, int id)
147 {
148     WNDPROC origCB;
149 
150     origCB = (WNDPROC) SetWindowLongPtr(GetDlgItem(hwnd, id), GWLP_USERDATA, 0);
151     if (origCB)
152         SetWindowLongPtr(GetDlgItem(hwnd, id), GWLP_WNDPROC, (LONG_PTR) origCB);
153 }
154 
155 /*
156  * Center a dialog window in the desktop window
157  * and set small and large icons to X icons.
158  */
159 
160 static void
winInitDialog(HWND hwndDlg)161 winInitDialog(HWND hwndDlg)
162 {
163     HWND hwndDesk;
164     RECT rc, rcDlg, rcDesk;
165     HICON hIcon, hIconSmall;
166 
167     hwndDesk = GetParent(hwndDlg);
168     if (!hwndDesk || IsIconic(hwndDesk))
169         hwndDesk = GetDesktopWindow();
170 
171     /* Remove minimize and maximize buttons */
172     SetWindowLongPtr(hwndDlg, GWL_STYLE, GetWindowLongPtr(hwndDlg, GWL_STYLE)
173                      & ~(WS_MAXIMIZEBOX | WS_MINIMIZEBOX));
174 
175     /* Set Window not to show in the task bar */
176     SetWindowLongPtr(hwndDlg, GWL_EXSTYLE,
177                      GetWindowLongPtr(hwndDlg, GWL_EXSTYLE) & ~WS_EX_APPWINDOW);
178 
179     /* Center dialog window in the screen. Not done for multi-monitor systems, where
180      * it is likely to end up split across the screens. In that case, it appears
181      * near the Tray icon.
182      */
183     if (GetSystemMetrics(SM_CMONITORS) > 1) {
184         /* Still need to refresh the frame change. */
185         SetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0,
186                      SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
187     }
188     else {
189         GetWindowRect(hwndDesk, &rcDesk);
190         GetWindowRect(hwndDlg, &rcDlg);
191         CopyRect(&rc, &rcDesk);
192 
193         OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top);
194         OffsetRect(&rc, -rc.left, -rc.top);
195         OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
196 
197         SetWindowPos(hwndDlg,
198                      HWND_TOPMOST,
199                      rcDesk.left + (rc.right / 2),
200                      rcDesk.top + (rc.bottom / 2),
201                      0, 0, SWP_NOSIZE | SWP_FRAMECHANGED);
202     }
203 
204     if (g_hIconX)
205         hIcon = g_hIconX;
206     else
207         hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_XWIN));
208 
209     if (g_hSmallIconX)
210         hIconSmall = g_hSmallIconX;
211     else
212         hIconSmall = LoadImage(g_hInstance,
213                                MAKEINTRESOURCE(IDI_XWIN), IMAGE_ICON,
214                                GetSystemMetrics(SM_CXSMICON),
215                                GetSystemMetrics(SM_CYSMICON), LR_SHARED);
216 
217     PostMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
218     PostMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall);
219 }
220 
221 /*
222  * Display the Exit dialog box
223  */
224 
225 void
winDisplayExitDialog(winPrivScreenPtr pScreenPriv)226 winDisplayExitDialog(winPrivScreenPtr pScreenPriv)
227 {
228     int i;
229     int liveClients = 0;
230 
231     /* Count up running clients (clients[0] is serverClient) */
232     for (i = 1; i < currentMaxClients; i++)
233         if (clients[i] != NullClient)
234             liveClients++;
235     /* Count down server internal clients */
236     if (pScreenPriv->pScreenInfo->fMultiWindow)
237         liveClients -= 2;       /* multiwindow window manager & XMsgProc  */
238     if (g_fClipboardStarted)
239         liveClients--;          /* clipboard manager */
240 
241     /* A user reported that this sometimes drops below zero. just eye-candy. */
242     if (liveClients < 0)
243         liveClients = 0;
244 
245     /* Don't show the exit confirmation dialog if SilentExit & no clients,
246        or ForceExit, is enabled */
247     if ((pref.fSilentExit && liveClients <= 0) || pref.fForceExit) {
248         if (g_hDlgExit != NULL) {
249             DestroyWindow(g_hDlgExit);
250             g_hDlgExit = NULL;
251         }
252         PostMessage(pScreenPriv->hwndScreen, WM_GIVEUP, 0, 0);
253         return;
254     }
255 
256     pScreenPriv->iConnectedClients = liveClients;
257 
258     /* Check if dialog already exists */
259     if (g_hDlgExit != NULL) {
260         /* Dialog box already exists, display it */
261         ShowWindow(g_hDlgExit, SW_SHOWDEFAULT);
262 
263         /* User has lost the dialog.  Show them where it is. */
264         SetForegroundWindow(g_hDlgExit);
265 
266         return;
267     }
268 
269     /* Create dialog box */
270     g_hDlgExit = CreateDialogParam(g_hInstance,
271                                    "EXIT_DIALOG",
272                                    pScreenPriv->hwndScreen,
273                                    winExitDlgProc, (LPARAM) pScreenPriv);
274 
275     /* Show the dialog box */
276     ShowWindow(g_hDlgExit, SW_SHOW);
277 
278     /* Needed to get keyboard controls (tab, arrows, enter, esc) to work */
279     SetForegroundWindow(g_hDlgExit);
280 
281     /* Set focus to the Cancel button */
282     PostMessage(g_hDlgExit, WM_NEXTDLGCTL,
283                 (WPARAM) GetDlgItem(g_hDlgExit, IDCANCEL), TRUE);
284 }
285 
286 #define CONNECTED_CLIENTS_FORMAT	"There %s currently %d client%s connected."
287 
288 /*
289  * Exit dialog window procedure
290  */
291 
292 static INT_PTR CALLBACK
winExitDlgProc(HWND hDialog,UINT message,WPARAM wParam,LPARAM lParam)293 winExitDlgProc(HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
294 {
295     static winPrivScreenPtr s_pScreenPriv = NULL;
296 
297     /* Branch on message type */
298     switch (message) {
299     case WM_INITDIALOG:
300     {
301         char *pszConnectedClients;
302 
303         /* Store pointers to private structures for future use */
304         s_pScreenPriv = (winPrivScreenPtr) lParam;
305 
306         winInitDialog(hDialog);
307 
308         /* Format the connected clients string */
309         if (asprintf(&pszConnectedClients, CONNECTED_CLIENTS_FORMAT,
310                      (s_pScreenPriv->iConnectedClients == 1) ? "is" : "are",
311                      s_pScreenPriv->iConnectedClients,
312                      (s_pScreenPriv->iConnectedClients == 1) ? "" : "s") == -1)
313             return TRUE;
314 
315         /* Set the number of connected clients */
316         SetWindowText(GetDlgItem(hDialog, IDC_CLIENTS_CONNECTED),
317                       pszConnectedClients);
318         free(pszConnectedClients);
319     }
320         return TRUE;
321 
322     case WM_COMMAND:
323         switch (LOWORD(wParam)) {
324         case IDOK:
325             /* Send message to call the GiveUp function */
326             PostMessage(s_pScreenPriv->hwndScreen, WM_GIVEUP, 0, 0);
327             DestroyWindow(g_hDlgExit);
328             g_hDlgExit = NULL;
329 
330             /* Fix to make sure keyboard focus isn't trapped */
331             PostMessage(s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
332             return TRUE;
333 
334         case IDCANCEL:
335             DestroyWindow(g_hDlgExit);
336             g_hDlgExit = NULL;
337 
338             /* Fix to make sure keyboard focus isn't trapped */
339             PostMessage(s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
340             return TRUE;
341         }
342         break;
343 
344     case WM_MOUSEMOVE:
345     case WM_NCMOUSEMOVE:
346         /* Show the cursor if it is hidden */
347         if (g_fSoftwareCursor && !g_fCursor) {
348             g_fCursor = TRUE;
349             ShowCursor(TRUE);
350         }
351         return TRUE;
352 
353     case WM_CLOSE:
354         DestroyWindow(g_hDlgExit);
355         g_hDlgExit = NULL;
356 
357         /* Fix to make sure keyboard focus isn't trapped */
358         PostMessage(s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
359         return TRUE;
360     }
361 
362     return FALSE;
363 }
364 
365 /*
366  * Display the Depth Change dialog box
367  */
368 
369 void
winDisplayDepthChangeDialog(winPrivScreenPtr pScreenPriv)370 winDisplayDepthChangeDialog(winPrivScreenPtr pScreenPriv)
371 {
372     /* Check if dialog already exists */
373     if (g_hDlgDepthChange != NULL) {
374         /* Dialog box already exists, display it */
375         ShowWindow(g_hDlgDepthChange, SW_SHOWDEFAULT);
376 
377         /* User has lost the dialog.  Show them where it is. */
378         SetForegroundWindow(g_hDlgDepthChange);
379 
380         return;
381     }
382 
383     /*
384      * Display a notification to the user that the visual
385      * will not be displayed until the Windows display depth
386      * is restored to the original value.
387      */
388     g_hDlgDepthChange = CreateDialogParam(g_hInstance,
389                                           "DEPTH_CHANGE_BOX",
390                                           pScreenPriv->hwndScreen,
391                                           winChangeDepthDlgProc,
392                                           (LPARAM) pScreenPriv);
393     /* Show the dialog box */
394     ShowWindow(g_hDlgDepthChange, SW_SHOW);
395 
396     if (!g_hDlgDepthChange)
397         ErrorF("winDisplayDepthChangeDialog - GetLastError: %d\n",
398                 (int) GetLastError());
399 
400     /* Minimize the display window */
401     ShowWindow(pScreenPriv->hwndScreen, SW_MINIMIZE);
402 }
403 
404 /*
405  * Process messages for the dialog that is displayed for
406  * disruptive screen depth changes.
407  */
408 
409 static INT_PTR CALLBACK
winChangeDepthDlgProc(HWND hwndDialog,UINT message,WPARAM wParam,LPARAM lParam)410 winChangeDepthDlgProc(HWND hwndDialog, UINT message,
411                       WPARAM wParam, LPARAM lParam)
412 {
413     static winPrivScreenPtr s_pScreenPriv = NULL;
414     static winScreenInfo *s_pScreenInfo = NULL;
415 
416 #if CYGDEBUG
417     winDebug("winChangeDepthDlgProc\n");
418 #endif
419 
420     /* Branch on message type */
421     switch (message) {
422     case WM_INITDIALOG:
423 #if CYGDEBUG
424         winDebug("winChangeDepthDlgProc - WM_INITDIALOG\n");
425 #endif
426 
427         /* Store pointers to private structures for future use */
428         s_pScreenPriv = (winPrivScreenPtr) lParam;
429         s_pScreenInfo = s_pScreenPriv->pScreenInfo;
430 
431 #if CYGDEBUG
432         winDebug("winChangeDepthDlgProc - WM_INITDIALOG - s_pScreenPriv: %p, "
433                  "s_pScreenInfo: %p\n",
434                  s_pScreenPriv, s_pScreenInfo);
435 #endif
436 
437 #if CYGDEBUG
438         winDebug("winChangeDepthDlgProc - WM_INITDIALOG - orig bpp: %u, "
439                  "current bpp: %d\n",
440                  (unsigned int)s_pScreenInfo->dwBPP,
441                  GetDeviceCaps(s_pScreenPriv->hdcScreen, BITSPIXEL));
442 #endif
443 
444         winInitDialog(hwndDialog);
445 
446         return TRUE;
447 
448     case WM_DISPLAYCHANGE:
449 #if CYGDEBUG
450         winDebug("winChangeDepthDlgProc - WM_DISPLAYCHANGE - orig bpp: %u, "
451                  "new bpp: %d\n",
452                  (unsigned int)s_pScreenInfo->dwBPP,
453                  GetDeviceCaps(s_pScreenPriv->hdcScreen, BITSPIXEL));
454 #endif
455 
456         /* Dismiss the dialog if the display returns to the original depth */
457         if (GetDeviceCaps(s_pScreenPriv->hdcScreen, BITSPIXEL) ==
458             s_pScreenInfo->dwBPP) {
459             ErrorF("winChangeDelthDlgProc - wParam == s_pScreenInfo->dwBPP\n");
460 
461             /* Depth has been restored, dismiss dialog */
462             DestroyWindow(g_hDlgDepthChange);
463             g_hDlgDepthChange = NULL;
464 
465             /* Flag that we have a valid screen depth */
466             s_pScreenPriv->fBadDepth = FALSE;
467         }
468         return TRUE;
469 
470     case WM_COMMAND:
471         switch (LOWORD(wParam)) {
472         case IDOK:
473         case IDCANCEL:
474             winDebug("winChangeDepthDlgProc - WM_COMMAND - IDOK or IDCANCEL\n");
475 
476             /*
477              * User dismissed the dialog, hide it until the
478              * display mode is restored.
479              */
480             ShowWindow(g_hDlgDepthChange, SW_HIDE);
481             return TRUE;
482         }
483         break;
484 
485     case WM_CLOSE:
486         winDebug("winChangeDepthDlgProc - WM_CLOSE\n");
487 
488         DestroyWindow(g_hDlgAbout);
489         g_hDlgAbout = NULL;
490 
491         /* Fix to make sure keyboard focus isn't trapped */
492         PostMessage(s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
493         return TRUE;
494     }
495 
496     return FALSE;
497 }
498 
499 /*
500  * Display the About dialog box
501  */
502 
503 void
winDisplayAboutDialog(winPrivScreenPtr pScreenPriv)504 winDisplayAboutDialog(winPrivScreenPtr pScreenPriv)
505 {
506     /* Check if dialog already exists */
507     if (g_hDlgAbout != NULL) {
508         /* Dialog box already exists, display it */
509         ShowWindow(g_hDlgAbout, SW_SHOWDEFAULT);
510 
511         /* User has lost the dialog.  Show them where it is. */
512         SetForegroundWindow(g_hDlgAbout);
513 
514         return;
515     }
516 
517     /*
518      * Display the about box
519      */
520     g_hDlgAbout = CreateDialogParam(g_hInstance,
521                                     "ABOUT_BOX",
522                                     pScreenPriv->hwndScreen,
523                                     winAboutDlgProc, (LPARAM) pScreenPriv);
524 
525     /* Show the dialog box */
526     ShowWindow(g_hDlgAbout, SW_SHOW);
527 
528     /* Needed to get keyboard controls (tab, arrows, enter, esc) to work */
529     SetForegroundWindow(g_hDlgAbout);
530 
531     /* Set focus to the OK button */
532     PostMessage(g_hDlgAbout, WM_NEXTDLGCTL,
533                 (WPARAM) GetDlgItem(g_hDlgAbout, IDOK), TRUE);
534 }
535 
536 /*
537  * Process messages for the about dialog.
538  */
539 
540 static INT_PTR CALLBACK
winAboutDlgProc(HWND hwndDialog,UINT message,WPARAM wParam,LPARAM lParam)541 winAboutDlgProc(HWND hwndDialog, UINT message, WPARAM wParam, LPARAM lParam)
542 {
543     static winPrivScreenPtr s_pScreenPriv = NULL;
544 
545 #if CYGDEBUG
546     winDebug("winAboutDlgProc\n");
547 #endif
548 
549     /* Branch on message type */
550     switch (message) {
551     case WM_INITDIALOG:
552 #if CYGDEBUG
553         winDebug("winAboutDlgProc - WM_INITDIALOG\n");
554 #endif
555 
556         /* Store pointer to private structure for future use */
557         s_pScreenPriv = (winPrivScreenPtr) lParam;
558 
559         winInitDialog(hwndDialog);
560 
561         /* Override the URL buttons */
562         winOverrideURLButton(hwndDialog, ID_ABOUT_WEBSITE);
563 
564         return TRUE;
565 
566     case WM_DRAWITEM:
567         /* Draw the URL buttons as needed */
568         winDrawURLWindow(lParam);
569         return TRUE;
570 
571     case WM_MOUSEMOVE:
572     case WM_NCMOUSEMOVE:
573         /* Show the cursor if it is hidden */
574         if (g_fSoftwareCursor && !g_fCursor) {
575             g_fCursor = TRUE;
576             ShowCursor(TRUE);
577         }
578         return TRUE;
579 
580     case WM_COMMAND:
581         switch (LOWORD(wParam)) {
582         case IDOK:
583         case IDCANCEL:
584             winDebug("winAboutDlgProc - WM_COMMAND - IDOK or IDCANCEL\n");
585 
586             DestroyWindow(g_hDlgAbout);
587             g_hDlgAbout = NULL;
588 
589             /* Fix to make sure keyboard focus isn't trapped */
590             PostMessage(s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
591 
592             /* Restore window procedures for URL buttons */
593             winUnoverrideURLButton(hwndDialog, ID_ABOUT_WEBSITE);
594 
595             return TRUE;
596 
597         case ID_ABOUT_WEBSITE:
598         {
599             const char *pszPath = __VENDORDWEBSUPPORT__;
600             INT_PTR iReturn;
601 
602             iReturn = (INT_PTR) ShellExecute(NULL,
603                                          "open",
604                                          pszPath, NULL, NULL, SW_MAXIMIZE);
605             if (iReturn < 32) {
606                 ErrorF("winAboutDlgProc - WM_COMMAND - ID_ABOUT_WEBSITE - "
607                        "ShellExecute failed: %d\n", (int)iReturn);
608 
609             }
610         }
611             return TRUE;
612         }
613         break;
614 
615     case WM_CLOSE:
616         winDebug("winAboutDlgProc - WM_CLOSE\n");
617 
618         DestroyWindow(g_hDlgAbout);
619         g_hDlgAbout = NULL;
620 
621         /* Fix to make sure keyboard focus isn't trapped */
622         PostMessage(s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
623 
624         /* Restore window procedures for URL buttons */
625         winUnoverrideURLButton(hwndDialog, ID_ABOUT_WEBSITE);
626 
627         return TRUE;
628     }
629 
630     return FALSE;
631 }
632