LINUX: afs_create infinite fetchStatus loop
[pkg-k5-afs_openafs.git] / src / WINNT / client_config / tab_prefs.cpp
blob5747f465476cf80f89f4ee50cf90fc9f7ed984e4
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
10 #include <winsock2.h>
11 #include <ws2tcpip.h>
13 extern "C" {
14 #include <afs/param.h>
15 #include <afs/stds.h>
18 #include "afs_config.h"
19 #include "tab_prefs.h"
20 #include <hashlist.h>
21 #include <stdlib.h>
25 * VARIABLES __________________________________________________________________
29 static struct l
31 CRITICAL_SECTION cs;
32 BOOL fThreadActive;
33 HWND hList;
34 } l;
36 #define cREALLOC_PREFS 32
38 #ifndef iswhite
39 #define iswhite(_ch) (((_ch)==TEXT(' ')) || ((_ch)==TEXT('\t')))
40 #endif
41 #ifndef iseol
42 #define iseol(_ch) (((_ch)==TEXT('\r')) || ((_ch)==TEXT('\n')))
43 #endif
44 #ifndef iswhiteeol
45 #define iswhiteeol(_ch) (iswhite(_ch) || iseol(_ch))
46 #endif
50 * PROTOTYPES _________________________________________________________________
54 void PrefsTab_OnInitDialog (HWND hDlg);
55 BOOL PrefsTab_OnApply (HWND hDlg);
56 void PrefsTab_OnRefresh (HWND hDlg);
57 void PrefsTab_OnFillList (HWND hDlg);
58 void PrefsTab_OnSelect (HWND hDlg);
59 void PrefsTab_OnUpDown (HWND hDlg, BOOL fDown);
60 void PrefsTab_OnAdd (HWND hDlg);
61 void PrefsTab_OnEdit (HWND hDlg);
62 void PrefsTab_OnImport (HWND hDlg);
64 void PrefsTab_MergeServerPrefs (PSERVERPREFS pGlobal, PSERVERPREFS pAdd);
65 void PrefsTab_AddItem (HWND hDlg, PSERVERPREF pPref, BOOL fSelect);
66 void PrefsTab_AddItem (HWND hDlg, LPCTSTR pszServer, int iRank);
68 DWORD WINAPI PrefsTab_RefreshThread (PVOID lp);
69 DWORD WINAPI PrefsTab_ThreadProc (PVOID lp);
70 void PrefsTab_ThreadProcFunc (PSERVERPREFS pPrefs, BOOL *pfStopFlag);
72 int CALLBACK PrefsTab_SortFunction (HWND hList, HLISTITEM hItem1, LPARAM lpItem1, HLISTITEM hItem2, LPARAM lpItem2);
74 BOOL CALLBACK IPKey_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData);
75 HASHVALUE CALLBACK IPKey_HashObject (LPHASHLISTKEY pKey, PVOID pObject);
76 HASHVALUE CALLBACK IPKey_HashData (LPHASHLISTKEY pKey, PVOID pData);
78 BOOL CALLBACK PrefsEdit_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
79 void PrefsEdit_OnInitDialog (HWND hDlg);
80 void PrefsEdit_OnOK (HWND hDlg);
81 void PrefsEdit_Enable (HWND hDlg);
85 * ROUTINES ___________________________________________________________________
89 BOOL CALLBACK PrefsTab_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
91 switch (msg)
93 case WM_INITDIALOG:
94 InitializeCriticalSection (&l.cs);
95 PrefsTab_OnInitDialog (hDlg);
96 break;
98 case WM_COMMAND:
99 switch (LOWORD(wp))
101 case IDAPPLY:
102 if (!PrefsTab_OnApply (hDlg))
103 SetWindowLongPtr (hDlg, DWLP_MSGRESULT, TRUE);
104 break;
106 case IDC_REFRESH:
107 PrefsTab_OnRefresh (hDlg);
108 break;
110 case IDC_SHOW_FS:
111 case IDC_SHOW_VLS:
112 PrefsTab_OnFillList (hDlg);
113 break;
115 case IDC_ADD:
116 PrefsTab_OnAdd (hDlg);
117 break;
119 case IDC_EDIT:
120 PrefsTab_OnEdit (hDlg);
121 break;
123 case IDC_UP:
124 PrefsTab_OnUpDown (hDlg, FALSE);
125 break;
127 case IDC_DOWN:
128 PrefsTab_OnUpDown (hDlg, TRUE);
129 break;
131 case IDC_IMPORT:
132 PrefsTab_OnImport (hDlg);
133 break;
135 case IDHELP:
136 PrefsTab_DlgProc (hDlg, WM_HELP, 0, 0);
137 break;
139 break;
141 case WM_HELP:
142 WinHelp (hDlg, g.szHelpFile, HELP_CONTEXT, IDH_AFSCONFIG_PREFS_NT);
143 break;
145 case WM_NOTIFY:
146 switch (((LPNMHDR)lp)->code)
148 case FLN_ITEMSELECT:
149 PrefsTab_OnSelect (hDlg);
150 break;
152 case FLN_LDBLCLICK:
153 if (IsWindowEnabled (GetDlgItem (hDlg, IDC_EDIT)))
154 PrefsTab_OnEdit (hDlg);
155 break;
157 break;
160 return FALSE;
164 void PrefsTab_OnInitDialog (HWND hDlg)
166 HICON hiUp = TaLocale_LoadIcon (IDI_UP);
167 HICON hiDown = TaLocale_LoadIcon (IDI_DOWN);
169 SendDlgItemMessage (hDlg, IDC_UP, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hiUp);
170 SendDlgItemMessage (hDlg, IDC_DOWN, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hiDown);
172 CheckDlgButton (hDlg, IDC_SHOW_FS, TRUE);
173 CheckDlgButton (hDlg, IDC_SHOW_VLS, FALSE);
175 l.hList = GetDlgItem (hDlg, IDC_LIST);
177 FASTLISTCOLUMN Column;
178 Column.dwFlags = FLCF_JUSTIFY_LEFT;
179 Column.cxWidth = 200;
180 GetString (Column.szText, IDS_PREFCOL_SERVER);
181 FastList_SetColumn (l.hList, 0, &Column);
183 Column.dwFlags = FLCF_JUSTIFY_RIGHT;
184 Column.cxWidth = 40;
185 GetString (Column.szText, IDS_PREFCOL_RANK);
186 FastList_SetColumn (l.hList, 1, &Column);
188 FastList_SetSortFunction (l.hList, PrefsTab_SortFunction);
190 PrefsTab_OnFillList (hDlg);
191 PrefsTab_OnRefresh (hDlg);
195 BOOL PrefsTab_CommitChanges (BOOL fForce)
197 HWND hDlg;
198 if ((hDlg = PropSheet_FindTabWindow (g.psh, (DLGPROC)PrefsTab_DlgProc)) == NULL)
199 return TRUE;
200 if (fForce)
201 SetWindowLongPtr (hDlg, DWLP_MSGRESULT, FALSE); // Make sure we try to apply
202 if (PrefsTab_OnApply (hDlg))
203 return TRUE;
204 SetWindowLongPtr (hDlg, DWLP_MSGRESULT, TRUE);
205 return FALSE;
209 BOOL PrefsTab_OnApply (HWND hDlg)
211 // Don't try to do anything if we've already failed the apply
212 if (GetWindowLongPtr (hDlg, DWLP_MSGRESULT))
213 return FALSE;
215 if (g.Configuration.pFServers && g.Configuration.fChangedPrefs)
217 if (!Config_SetServerPrefs (g.Configuration.pFServers))
218 return FALSE;
220 if (g.Configuration.pVLServers && g.Configuration.fChangedPrefs)
222 if (!Config_SetServerPrefs (g.Configuration.pVLServers))
223 return FALSE;
225 g.Configuration.fChangedPrefs = FALSE;
226 return TRUE;
230 void PrefsTab_OnRefresh (HWND hDlg)
232 DWORD idThread;
233 CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)PrefsTab_RefreshThread, (PVOID)hDlg, 0, &idThread);
237 void PrefsTab_OnFillList (HWND hDlg)
239 EnterCriticalSection (&l.cs);
240 BOOL fVLServers = IsDlgButtonChecked (hDlg, IDC_SHOW_VLS);
242 // Empty the fastlist, and clear from the lists any mention of HLISTITEMs.
244 FastList_Begin (l.hList);
245 FastList_RemoveAll (l.hList);
247 if (g.Configuration.pVLServers)
249 for (size_t ii = 0; ii < g.Configuration.pVLServers->cPrefs; ++ii)
250 g.Configuration.pVLServers->aPrefs[ ii ].hItem = NULL;
252 if (g.Configuration.pFServers)
254 for (size_t ii = 0; ii < g.Configuration.pFServers->cPrefs; ++ii)
255 g.Configuration.pFServers->aPrefs[ ii ].hItem = NULL;
258 // Fill in the fastlist by adding entries from the appropriate prefslist.
260 PSERVERPREFS pPrefs = (fVLServers) ? g.Configuration.pVLServers : g.Configuration.pFServers;
261 if (pPrefs)
263 for (size_t ii = 0; ii < pPrefs->cPrefs; ++ii)
265 if (!pPrefs->aPrefs[ ii ].ipServer)
266 continue;
268 TCHAR szItem[ cchRESOURCE ];
269 if (!pPrefs->aPrefs[ ii ].szServer[0])
271 lstrcpy (szItem, inet_ntoa (*(struct in_addr *)&pPrefs->aPrefs[ ii ].ipServer));
273 else
275 wsprintf (szItem, TEXT("%s (%s)"),
276 pPrefs->aPrefs[ ii ].szServer,
277 inet_ntoa (*(struct in_addr *)&pPrefs->aPrefs[ ii ].ipServer));
280 FASTLISTADDITEM ai;
281 memset (&ai, 0x00, sizeof(FASTLISTADDITEM));
282 ai.iFirstImage = IMAGE_NOIMAGE;
283 ai.iSecondImage = IMAGE_NOIMAGE;
284 ai.pszText = szItem;
285 ai.lParam = ii;
286 pPrefs->aPrefs[ ii ].hItem = FastList_AddItem (l.hList, &ai);
288 wsprintf (szItem, TEXT("%ld"), pPrefs->aPrefs[ ii ].iRank);
289 FastList_SetItemText (l.hList, pPrefs->aPrefs[ ii ].hItem, 1, szItem);
293 // Okay, we're done!
295 FastList_End (l.hList);
296 LeaveCriticalSection (&l.cs);
297 PrefsTab_OnSelect (hDlg);
301 void PrefsTab_OnSelect (HWND hDlg)
303 if (IsWindowEnabled (l.hList))
305 HLISTITEM hItem = FastList_FindFirstSelected (l.hList);
306 HLISTITEM hItemFirst = FastList_FindFirst (l.hList);
307 HLISTITEM hItemNext = FastList_FindNext (l.hList, hItem);
309 EnableWindow (GetDlgItem (hDlg, IDC_UP), (hItem && (hItem != hItemFirst)));
310 EnableWindow (GetDlgItem (hDlg, IDC_DOWN), (hItem && hItemNext));
311 EnableWindow (GetDlgItem (hDlg, IDC_ADD), TRUE);
312 EnableWindow (GetDlgItem (hDlg, IDC_IMPORT), TRUE);
313 EnableWindow (GetDlgItem (hDlg, IDC_EDIT), !!hItem);
318 void PrefsTab_OnUpDown (HWND hDlg, BOOL fDown)
320 BOOL fVLServers = IsDlgButtonChecked (hDlg, IDC_SHOW_VLS);
321 PSERVERPREFS pPrefs = (fVLServers) ? g.Configuration.pVLServers : g.Configuration.pFServers;
323 HLISTITEM hItem;
324 if ((hItem = FastList_FindFirstSelected (l.hList)) == NULL)
325 return;
327 HLISTITEM hOther;
328 hOther = (fDown) ? FastList_FindNext(l.hList,hItem) : FastList_FindPrevious(l.hList,hItem);
329 if (hOther == NULL)
330 return;
332 size_t iItem = (size_t)FastList_GetItemParam (l.hList, hItem);
333 size_t iOther = (size_t)FastList_GetItemParam (l.hList, hOther);
335 if (!pPrefs || (pPrefs->cPrefs <= iItem) || (pPrefs->cPrefs <= iOther))
336 return;
338 FastList_Begin (l.hList);
340 PSERVERPREF pPref1 = &pPrefs->aPrefs[ iItem ];
341 PSERVERPREF pPref2 = &pPrefs->aPrefs[ iOther ];
343 if (pPref1->iRank == pPref2->iRank)
345 if (fDown && (pPref1->iRank < 65534))
346 pPref1->iRank ++;
347 else if ((!fDown) && (pPref1->iRank > 1))
348 pPref1->iRank --;
349 pPref1->fChanged = TRUE;
351 else // (pPref1->iRating != pPref2->iRating)
353 pPref1->iRank ^= pPref2->iRank;
354 pPref2->iRank ^= pPref1->iRank;
355 pPref1->iRank ^= pPref2->iRank;
356 pPref1->fChanged = TRUE;
357 pPref2->fChanged = TRUE;
360 TCHAR szText[ cchRESOURCE ];
361 wsprintf (szText, TEXT("%ld"), pPref1->iRank);
362 FastList_SetItemText (l.hList, pPref1->hItem, 1, szText);
364 wsprintf (szText, TEXT("%ld"), pPref2->iRank);
365 FastList_SetItemText (l.hList, pPref2->hItem, 1, szText);
367 FastList_EnsureVisible (l.hList, hItem);
368 FastList_End (l.hList);
369 PrefsTab_OnSelect (hDlg);
371 g.Configuration.fChangedPrefs = TRUE;
375 void PrefsTab_OnAdd (HWND hDlg)
377 BOOL fVLServers = IsDlgButtonChecked (hDlg, IDC_SHOW_VLS);
378 PSERVERPREFS pPrefs = (fVLServers) ? g.Configuration.pVLServers : g.Configuration.pFServers;
380 SERVERPREF Pref;
381 memset (&Pref, 0x00, sizeof(SERVERPREF));
382 Pref.iRank = 30000;
384 if (ModalDialogParam (IDD_PREFS_EDIT, GetParent(hDlg), (DLGPROC)PrefsEdit_DlgProc, (LPARAM)&Pref) == IDOK)
386 PrefsTab_AddItem (hDlg, &Pref, TRUE);
387 PrefsTab_OnSelect (hDlg);
388 g.Configuration.fChangedPrefs = TRUE;
393 void PrefsTab_OnEdit (HWND hDlg)
395 BOOL fVLServers = IsDlgButtonChecked (hDlg, IDC_SHOW_VLS);
396 PSERVERPREFS pPrefs = (fVLServers) ? g.Configuration.pVLServers : g.Configuration.pFServers;
398 HLISTITEM hItem;
399 if ((hItem = FastList_FindFirstSelected (l.hList)) == NULL)
400 return;
402 PSERVERPREF pPref = &pPrefs->aPrefs[ FastList_GetItemParam (l.hList, hItem) ];
404 if (ModalDialogParam (IDD_PREFS_EDIT, GetParent(hDlg), (DLGPROC)PrefsEdit_DlgProc, (LPARAM)pPref) == IDOK)
406 FastList_Begin (l.hList);
408 TCHAR szText[ cchRESOURCE ];
409 wsprintf (szText, TEXT("%ld"), pPref->iRank);
410 FastList_SetItemText (l.hList, pPref->hItem, 1, szText);
411 pPref->fChanged = TRUE;
413 FastList_EnsureVisible (l.hList, hItem);
414 FastList_End (l.hList);
415 PrefsTab_OnSelect (hDlg);
416 g.Configuration.fChangedPrefs = TRUE;
421 void PrefsTab_OnImport (HWND hDlg)
423 BOOL fVLServers = IsDlgButtonChecked (hDlg, IDC_SHOW_VLS);
424 PSERVERPREFS pPrefs = (fVLServers) ? g.Configuration.pVLServers : g.Configuration.pFServers;
426 TCHAR szFilename[ MAX_PATH ] = TEXT("");
427 if (Browse_Open (hDlg, szFilename, NULL, IDS_FILTER_TXT, 0, NULL, 0))
429 FastList_Begin (l.hList);
431 // Open the file and read it into memory.
433 HANDLE fh;
434 if ((fh = CreateFile (szFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
436 DWORD cbLength = GetFileSize (fh, NULL);
437 LPTSTR pszBuffer = (LPTSTR)Allocate (sizeof(TCHAR) * (cbLength +2));
439 DWORD cbRead;
440 if (ReadFile (fh, pszBuffer, cbLength, &cbRead, NULL))
442 pszBuffer[ cbRead ] = TEXT('\0');
443 pszBuffer[ cbRead+1 ] = TEXT('\0');
445 // Scan the file line-by-line...
447 LPTSTR pszStart = pszBuffer;
448 while (pszStart && *pszStart)
450 while (iswhiteeol(*pszStart))
451 ++pszStart;
453 LPTSTR pszEnd = pszStart;
454 while (*pszEnd && !iseol(*pszEnd))
455 ++pszEnd;
456 *pszEnd++ = TEXT('\0');
458 // Okay, {pszStart} points to a 0-terminated line in this file.
459 // If the line starts with '#', ';' or '//', skip it.
461 if ( (pszStart[0] != TEXT('#')) &&
462 (pszStart[0] != TEXT(';')) &&
463 ((pszStart[0] != TEXT('/')) || (pszStart[1] != TEXT('/'))) )
465 // Break the line up into two sections: the machine name,
466 // and the ranking.
468 TCHAR szServer[ MAX_PATH ];
469 LPTSTR pszOut;
470 for (pszOut = szServer; *pszStart && !iswhite(*pszStart); )
471 *pszOut++ = *pszStart++;
472 *pszOut = TEXT('\0');
474 while (iswhite(*pszStart))
475 ++pszStart;
477 TCHAR szRank[ MAX_PATH ];
478 for (pszOut = szRank; *pszStart && !iswhite(*pszStart); )
479 *pszOut++ = *pszStart++;
480 *pszOut = TEXT('\0');
482 PrefsTab_AddItem (hDlg, szServer, atoi(szRank));
485 // Process the next line in the file.
487 pszStart = pszEnd;
491 Free (pszBuffer);
492 CloseHandle (fh);
495 // Restart the background thread, to resolve unknown IP address
497 PrefsTab_OnRefresh (hDlg);
498 FastList_End (l.hList);
499 g.Configuration.fChangedPrefs = TRUE;
504 void PrefsTab_MergeServerPrefs (PSERVERPREFS pGlobal, PSERVERPREFS pAdd)
506 LPHASHLIST pList = New (HASHLIST);
507 LPHASHLISTKEY pKey = pList->CreateKey (TEXT("IP Address"), IPKey_Compare, IPKey_HashObject, IPKey_HashData);
509 size_t ii;
510 for (ii = 0; ii < pGlobal->cPrefs; ++ii)
512 if (!pGlobal->aPrefs[ ii ].ipServer)
513 continue;
514 pList->Add (&pGlobal->aPrefs[ ii ]);
517 size_t iOut = 0;
518 for (ii = 0; ii < pAdd->cPrefs; ++ii)
520 if (!pAdd->aPrefs[ ii ].ipServer)
521 continue;
523 // The whole point of using a hashlist here is to allow this next call--
524 // on a hashlist, lookup and add are both constant-time, turning this
525 // merge into O(N) instead of (O(N^2))
527 if (pKey->GetFirstObject (&pAdd->aPrefs[ ii ].ipServer))
528 continue;
530 for ( ; iOut < pGlobal->cPrefs; ++iOut)
532 if (!pGlobal->aPrefs[ iOut ].ipServer)
533 break;
536 if (REALLOC (pGlobal->aPrefs, pGlobal->cPrefs, 1+iOut, cREALLOC_PREFS))
538 memcpy (&pGlobal->aPrefs[ iOut ], &pAdd->aPrefs[ ii ], sizeof(SERVERPREFS));
539 iOut++;
543 Delete (pList);
547 void PrefsTab_AddItem (HWND hDlg, PSERVERPREF pPref, BOOL fSelect)
549 BOOL fVLServers = IsDlgButtonChecked (hDlg, IDC_SHOW_VLS);
550 PSERVERPREFS pPrefs = (fVLServers) ? g.Configuration.pVLServers : g.Configuration.pFServers;
552 size_t ii;
553 for (ii = 0; ii < pPrefs->cPrefs; ++ii)
555 if (pPrefs->aPrefs[ ii ].ipServer == pPref->ipServer)
556 break;
558 if (ii == pPrefs->cPrefs)
560 for (ii = 0; ii < pPrefs->cPrefs; ++ii)
562 if (!pPrefs->aPrefs[ ii ].ipServer)
563 break;
565 if (!REALLOC (pPrefs->aPrefs, pPrefs->cPrefs, 1+ii, cREALLOC_PREFS))
566 return;
567 memcpy (&pPrefs->aPrefs[ ii ], pPref, sizeof(SERVERPREF));
570 FastList_Begin (l.hList);
572 if (!pPrefs->aPrefs[ ii ].hItem)
574 TCHAR szItem[ cchRESOURCE ];
575 if (!pPrefs->aPrefs[ ii ].szServer[0])
577 lstrcpy (szItem, inet_ntoa (*(struct in_addr *)&pPrefs->aPrefs[ ii ].ipServer));
579 else
581 wsprintf (szItem, TEXT("%s (%s)"),
582 pPrefs->aPrefs[ ii ].szServer,
583 inet_ntoa (*(struct in_addr *)&pPrefs->aPrefs[ ii ].ipServer));
586 FASTLISTADDITEM ai;
587 memset (&ai, 0x00, sizeof(FASTLISTADDITEM));
588 ai.iFirstImage = IMAGE_NOIMAGE;
589 ai.iSecondImage = IMAGE_NOIMAGE;
590 ai.pszText = szItem;
591 ai.lParam = ii;
592 pPrefs->aPrefs[ ii ].hItem = FastList_AddItem (l.hList, &ai);
595 TCHAR szText[ cchRESOURCE ];
596 wsprintf (szText, TEXT("%ld"), pPrefs->aPrefs[ ii ].iRank);
597 FastList_SetItemText (l.hList, pPrefs->aPrefs[ ii ].hItem, 1, szText);
598 pPrefs->aPrefs[ ii ].fChanged = TRUE;
600 FastList_End (l.hList);
602 if (fSelect)
604 FastList_SelectItem (l.hList, pPrefs->aPrefs[ ii ].hItem, TRUE);
605 FastList_SetFocus (l.hList, pPrefs->aPrefs[ ii ].hItem);
606 FastList_EnsureVisible (l.hList, pPrefs->aPrefs[ ii ].hItem);
607 PrefsTab_OnSelect (hDlg);
612 void PrefsTab_AddItem (HWND hDlg, LPCTSTR pszServer, int iRank)
614 if ((iRank < 1) || (iRank > 65534))
615 return;
617 SERVERPREF Pref;
618 memset (&Pref, 0x00, sizeof(SERVERPREF));
619 Pref.iRank = iRank;
621 // If the server's name is an IP address, we'll translate it later
622 // when we do them en masse.
624 if (isdigit (pszServer[0]))
626 if ((Pref.ipServer = inet_addr (pszServer)) == INADDR_NONE)
627 return;
629 else // (!isdigit (pszServer[0]))
631 HOSTENT *pEntry;
632 if ((pEntry = gethostbyname (pszServer)) != NULL)
634 lstrcpy (Pref.szServer, pEntry->h_name);
635 Pref.ipServer = *(int *)pEntry->h_addr;
639 PrefsTab_AddItem (hDlg, &Pref, FALSE);
643 DWORD WINAPI PrefsTab_RefreshThread (PVOID lp)
645 HWND hDlg = (HWND)lp;
646 static BOOL *pfStopFlag = NULL;
648 // We may have a background thread or two working on resolving IP addresses.
649 // Flag them to stop.
651 EnterCriticalSection (&l.cs);
652 if (l.fThreadActive)
654 if (pfStopFlag)
655 *pfStopFlag = FALSE;
657 pfStopFlag = NULL; // Thread will free this when it terminates
659 // Retrieve PSERVERPREFS structures, and merge them into our globals
661 PSERVERPREFS pVLServers = Config_GetServerPrefs (TRUE);
662 PSERVERPREFS pFServers = Config_GetServerPrefs (FALSE);
664 if (!g.Configuration.pVLServers)
665 g.Configuration.pVLServers = pVLServers;
666 else if (g.Configuration.pVLServers && pVLServers)
667 PrefsTab_MergeServerPrefs (g.Configuration.pVLServers, pVLServers);
669 if (!g.Configuration.pFServers)
670 g.Configuration.pFServers = pFServers;
671 else if (g.Configuration.pFServers && pFServers)
672 PrefsTab_MergeServerPrefs (g.Configuration.pFServers, pFServers);
674 // Add entries to the fastlist
676 PrefsTab_OnFillList (hDlg);
678 // Fire up a background thread to resolve IP addresses into server names
680 pfStopFlag = New (BOOL);
681 *pfStopFlag = FALSE;
683 DWORD idThread;
684 CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)PrefsTab_ThreadProc, (PVOID)pfStopFlag, 0, &idThread);
685 l.fThreadActive = TRUE;
687 // Enable or disable controls based on whether the service is running
689 BOOL fRunning = (Config_GetServiceState() == SERVICE_RUNNING) ? TRUE : FALSE;
691 EnableWindow (GetDlgItem (hDlg, IDC_SHOW_FS), fRunning);
692 EnableWindow (GetDlgItem (hDlg, IDC_SHOW_VLS), fRunning);
693 EnableWindow (GetDlgItem (hDlg, IDC_LIST), fRunning);
694 EnableWindow (GetDlgItem (hDlg, IDC_UP), fRunning);
695 EnableWindow (GetDlgItem (hDlg, IDC_DOWN), fRunning);
696 EnableWindow (GetDlgItem (hDlg, IDC_IMPORT), fRunning);
697 EnableWindow (GetDlgItem (hDlg, IDC_ADD), fRunning);
698 EnableWindow (GetDlgItem (hDlg, IDC_EDIT), fRunning);
699 PrefsTab_OnSelect (hDlg);
701 TCHAR szText[ cchRESOURCE ];
702 GetString (szText, (fRunning) ? IDS_TIP_PREFS : IDS_WARN_STOPPED);
703 SetDlgItemText (hDlg, IDC_WARN, szText);
705 // We're done!
707 LeaveCriticalSection (&l.cs);
708 return 0;
712 DWORD WINAPI PrefsTab_ThreadProc (PVOID lp)
714 BOOL *pfStopFlag = (BOOL*)lp;
715 if (pfStopFlag)
717 PrefsTab_ThreadProcFunc (g.Configuration.pFServers, pfStopFlag);
718 PrefsTab_ThreadProcFunc (g.Configuration.pVLServers, pfStopFlag);
720 l.fThreadActive = FALSE;
721 Delete (pfStopFlag);
723 return 0;
727 void PrefsTab_ThreadProcFunc (PSERVERPREFS pPrefs, BOOL *pfStopFlag)
729 for (size_t ii = 0; ; ++ii)
731 // Find the next IP address to translate
733 EnterCriticalSection (&l.cs);
735 if ( (*pfStopFlag) || (ii >= pPrefs->cPrefs) )
737 LeaveCriticalSection (&l.cs);
738 break;
741 int ipServer;
742 if ( ((ipServer = pPrefs->aPrefs[ ii ].ipServer) == 0) ||
743 (pPrefs->aPrefs[ ii ].szServer[0] != TEXT('\0')) )
745 LeaveCriticalSection (&l.cs);
746 continue;
749 LeaveCriticalSection (&l.cs);
751 // Translate this IP address into a name
753 HOSTENT *pEntry;
754 if ((pEntry = gethostbyaddr ((char*)&ipServer, sizeof(ipServer), AF_INET)) == NULL)
755 continue;
757 // Update the SERVERPREFS list, and if necessary, update the display
758 // to show the server's name
760 EnterCriticalSection (&l.cs);
762 if (!*pfStopFlag)
764 if ((ii < pPrefs->cPrefs) && (ipServer == pPrefs->aPrefs[ ii ].ipServer))
766 lstrcpy (pPrefs->aPrefs[ ii ].szServer, pEntry->h_name);
767 if (pPrefs->aPrefs[ ii ].szServer[0])
769 if (pPrefs->aPrefs[ ii ].hItem)
771 TCHAR szItem[ cchRESOURCE ];
772 wsprintf (szItem, TEXT("%s (%s)"),
773 pPrefs->aPrefs[ ii ].szServer,
774 inet_ntoa (*(struct in_addr *)&pPrefs->aPrefs[ ii ].ipServer));
776 FastList_SetItemText (l.hList, pPrefs->aPrefs[ ii ].hItem, 0, szItem);
782 LeaveCriticalSection (&l.cs);
787 int CALLBACK PrefsTab_SortFunction (HWND hList, HLISTITEM hItem1, LPARAM lpItem1, HLISTITEM hItem2, LPARAM lpItem2)
789 static PSERVERPREFS pPrefs = NULL;
790 if (!hItem1 || !hItem2)
792 BOOL fVLServers = IsDlgButtonChecked (GetParent(hList), IDC_SHOW_VLS);
793 pPrefs = (fVLServers) ? g.Configuration.pVLServers : g.Configuration.pFServers;
794 return 0;
797 if (!pPrefs || (pPrefs->cPrefs <= (size_t)lpItem1) || (pPrefs->cPrefs <= (size_t)lpItem2))
798 return 0;
800 PSERVERPREF pPref1 = &pPrefs->aPrefs[ lpItem1 ];
801 PSERVERPREF pPref2 = &pPrefs->aPrefs[ lpItem2 ];
803 if (pPref1->iRank != pPref2->iRank)
804 return pPref1->iRank - pPref2->iRank;
806 ULONG ip1 = (ULONG)htonl (pPref1->ipServer);
807 ULONG ip2 = (ULONG)htonl (pPref2->ipServer);
808 return (ip1 < ip2) ? -1 : 1;
812 BOOL CALLBACK IPKey_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
814 return (((PSERVERPREF)pObject)->ipServer == *(int*)pData);
817 HASHVALUE CALLBACK IPKey_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
819 return IPKey_HashData (pKey, &((PSERVERPREF)pObject)->ipServer);
822 HASHVALUE CALLBACK IPKey_HashData (LPHASHLISTKEY pKey, PVOID pData)
824 return *(int*)pData;
828 BOOL CALLBACK PrefsEdit_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
830 switch (msg)
832 case WM_INITDIALOG:
833 SetWindowLongPtr (hDlg, DWLP_USER, lp);
834 PrefsEdit_OnInitDialog (hDlg);
835 PrefsEdit_Enable (hDlg);
836 break;
838 case WM_COMMAND:
839 switch (LOWORD(wp))
841 case IDC_SERVER:
842 PrefsEdit_Enable (hDlg);
843 break;
845 case IDOK:
846 PrefsEdit_OnOK (hDlg);
847 break;
849 case IDCANCEL:
850 EndDialog (hDlg, IDCANCEL);
851 break;
853 case IDHELP:
854 PrefsEdit_DlgProc (hDlg, WM_HELP, 0, 0);
855 break;
857 break;
859 case WM_HELP:
860 WinHelp (hDlg, g.szHelpFile, HELP_CONTEXT, IDH_AFSCONFIG_PREFS_NT_ADDEDIT);
861 break;
864 return FALSE;
868 void PrefsEdit_OnInitDialog (HWND hDlg)
870 PSERVERPREF pPref = (PSERVERPREF)GetWindowLongPtr (hDlg, DWLP_USER);
872 if (pPref->ipServer)
873 EnableWindow (GetDlgItem (hDlg, IDC_SERVER), FALSE);
875 if (pPref->szServer[0])
877 SetDlgItemText (hDlg, IDC_SERVER, pPref->szServer);
879 else if (pPref->ipServer)
881 SetDlgItemText (hDlg, IDC_SERVER, inet_ntoa (*(struct in_addr *)&pPref->ipServer));
884 CreateSpinner (GetDlgItem (hDlg, IDC_RANK), 10, FALSE, 1, pPref->iRank, 65534);
888 void PrefsEdit_OnOK (HWND hDlg)
890 PSERVERPREF pPref = (PSERVERPREF)GetWindowLongPtr (hDlg, DWLP_USER);
891 pPref->iRank = SP_GetPos (GetDlgItem (hDlg, IDC_RANK));
893 if (IsWindowEnabled (GetDlgItem (hDlg, IDC_SERVER)))
895 BOOL rc = TRUE;
896 ULONG status = 0;
898 TCHAR szServer[ cchRESOURCE ];
899 GetDlgItemText (hDlg, IDC_SERVER, szServer, cchRESOURCE);
900 if (isdigit (szServer[0]))
902 if ((pPref->ipServer = inet_addr (szServer)) == INADDR_NONE)
904 rc = FALSE;
905 status = WSAGetLastError();
907 else
909 HOSTENT *pEntry;
910 if ((pEntry = gethostbyaddr ((char*)&pPref->ipServer, sizeof(pPref->ipServer), AF_INET)) != NULL)
911 lstrcpy (pPref->szServer, pEntry->h_name);
914 else // (!isdigit(pData->szServer[0]))
916 HOSTENT *pEntry;
917 if ((pEntry = gethostbyname (szServer)) == NULL)
919 rc = FALSE;
920 status = WSAGetLastError();
922 else
924 lstrcpy (pPref->szServer, pEntry->h_name);
925 pPref->ipServer = *(int *)pEntry->h_addr;
929 if (!rc)
931 Message (MB_ICONHAND | MB_OK, GetErrorTitle(), IDS_PREFERROR_RESOLVE, TEXT("%s%08lX"), szServer, status);
932 return;
936 EndDialog (hDlg, IDOK);
940 void PrefsEdit_Enable (HWND hDlg)
942 TCHAR szServer[ cchRESOURCE ];
943 GetDlgItemText (hDlg, IDC_SERVER, szServer, cchRESOURCE);
945 EnableWindow (GetDlgItem (hDlg, IDOK), !!szServer[0]);