c6d1938a28219d2d4570614944200da0a5e233d2
[openafs.git] / src / WINNT / client_config / config.cpp
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
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  */
9
10 #include <winsock2.h>
11 #include <ws2tcpip.h>
12
13 extern "C" {
14 #include <afs/param.h>
15 #include <afs/stds.h>
16 }
17
18 #include "afs_config.h"
19 #include <WINNT\afsreg.h>
20
21 extern "C" {
22
23 #include "../afsd/fs_utils.h"
24
25 #define __CM_CONFIG_INTERFACES_ONLY__
26 #include "../afsd/cm_config.h"
27
28 #include "../afsd/cm_nls.h"
29 #define __CM_IOCTL_INTERFACES_ONLY__
30 #include "../afsd/cm_ioctl.h"
31
32 } // extern "C"
33
34
35 #define cREALLOC_PREFS       32
36
37 #define cSERVERPREFS_CHUNK  256
38
39 #define PIOCTL_MAXSIZE     2048
40
41
42
43 /*
44  * ROUTINES ___________________________________________________________________
45  *
46  */
47
48 static DWORD log2 (DWORD dwValue)
49 {
50    DWORD dwLog;
51    for (dwLog = 0; (DWORD)(1<<dwLog) < dwValue; ++dwLog)
52       ;
53    return dwLog;
54 }
55
56 DWORD Config_GetServiceState (void)
57 {
58    if (!g.fIsWinNT)
59       {
60       TCHAR szGateway[ cchRESOURCE ] = TEXT("");
61       Config_GetGatewayName (szGateway);
62       return (szGateway[0]) ? SERVICE_RUNNING : SERVICE_STOPPED;
63       }
64
65    SERVICE_STATUS Status;
66    memset (&Status, 0x00, sizeof(Status));
67
68    SC_HANDLE hManager;
69    if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
70       {
71       SC_HANDLE hService;
72       if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
73          {
74          QueryServiceStatus (hService, &Status);
75          CloseServiceHandle (hService);
76          }
77
78       CloseServiceHandle (hManager);
79       }
80
81    return Status.dwCurrentState;
82 }
83
84
85 /*
86  * Configuration Routine ______________________________________________________
87  *
88  */
89
90 void Config_GetGatewayFlag (BOOL *pfFlag)
91 {
92     if (!Config_ReadGlobalNum (TEXT("IsGateway"), (DWORD*)pfFlag))
93         *pfFlag = FALSE;
94 }
95
96
97 BOOL Config_SetGatewayFlag (BOOL fFlag, ULONG *pStatus)
98 {
99     Config_WriteGlobalNum (TEXT("IsGateway"), fFlag);
100     g.fNeedRestart = TRUE;
101     return TRUE;
102 }
103
104
105 void Config_GetGatewayName (LPTSTR pszName)
106 {
107     if (!Config_ReadGlobalString (TEXT("Gateway"), pszName, MAX_PATH))
108         GetString (pszName, IDS_GATEWAY_UNKNOWN);
109     else if (!*pszName)
110         GetString (pszName, IDS_GATEWAY_UNKNOWN);
111 }
112
113
114 BOOL Config_SetGatewayName (LPCTSTR pszName, ULONG *pStatus)
115 {
116    TCHAR szBogus[ cchRESOURCE ];
117    GetString (szBogus, IDS_GATEWAY_UNKNOWN);
118    if (!lstrcmpi (szBogus, pszName))
119       {
120       Config_WriteGlobalString (TEXT("Gateway"), TEXT(""));
121       }
122    else
123       {
124       Config_WriteGlobalString (TEXT("Gateway"), pszName);
125       }
126
127    return TRUE;
128 }
129
130
131 void Config_FixGatewayDrives (void)
132 {
133    // Zip through the user's network drives and reconnect
134    // them as necessary.
135    //
136    for (TCHAR chDrive = chDRIVE_A; chDrive <= chDRIVE_Z; ++chDrive)
137       {
138       TCHAR szSubmount[ MAX_PATH ];
139       if (!GetDriveSubmount (chDrive, szSubmount))
140          continue;
141
142       // We've got a mapping into AFS!  Remove it, rather forcefully.
143       //
144       TCHAR szDrive[] = "@:";
145       szDrive[0] = chDrive;
146       WNetCancelConnection (szDrive, TRUE);
147       }
148
149    // Now recreate our drive mappings, based on the user's already-
150    // specified preferences.
151    //
152    DRIVEMAPLIST List;
153    QueryDriveMapList (&List);
154
155    for (size_t ii = 0; ii < 26; ++ii)
156       {
157       if (!List.aDriveMap[ii].szMapping[0])
158          continue;
159       ActivateDriveMap (List.aDriveMap[ii].chDrive, List.aDriveMap[ii].szMapping, List.aDriveMap[ii].szSubmount, List.aDriveMap[ii].fPersistent);
160       }
161 }
162
163
164 void Config_GetCellName (LPTSTR pszName)
165 {
166    if (!Config_ReadGlobalString (TEXT("Cell"), pszName, MAX_PATH))
167       GetString (pszName, IDS_CELL_UNKNOWN);
168    else if (!*pszName)
169       GetString (pszName, IDS_CELL_UNKNOWN);
170 }
171
172
173 BOOL Config_ContactGateway (LPTSTR pszGateway, LPTSTR pszCell)
174 {
175    // pszCell is MAX_PATH
176    BOOL rc = FALSE;
177
178    BYTE OutData[ PIOCTL_MAXSIZE ];
179    memset (OutData, 0x00, sizeof(OutData));
180
181    struct ViceIoctl IOInfo;
182    IOInfo.in_size = 0;
183    IOInfo.in = 0;
184    IOInfo.out = (char *)OutData;
185    IOInfo.out_size = PIOCTL_MAXSIZE;
186
187    TCHAR szOldGateway[ MAX_PATH ];
188    Config_GetGatewayName (szOldGateway);
189    Config_SetGatewayName (pszGateway);
190
191    ULONG status;
192    if ((status = pioctl (0, VIOC_GET_WS_CELL, &IOInfo, 1)) == 0)
193    {
194        OutData[min(PIOCTL_MAXSIZE, MAX_PATH) - 1] = '\0';
195        if (OutData[0])
196        {
197            lstrcpy (pszCell, (LPCTSTR)OutData);
198            rc = TRUE;
199        }
200    }
201
202    Config_SetGatewayName (szOldGateway);
203
204    return rc;
205 }
206
207
208 BOOL Config_SetCellName (LPCTSTR pszName, ULONG *pStatus)
209 {
210    TCHAR szBogus[ cchRESOURCE ];
211    GetString (szBogus, IDS_CELL_UNKNOWN);
212    if (lstrcmpi (szBogus, pszName))
213       {
214       Config_WriteGlobalString (TEXT("Cell"), pszName);
215       g.fNeedRestart = TRUE;
216       }
217    return TRUE;
218 }
219
220 #if 0
221 /*      These two functions are not needed as of the 1.2.2a updates.
222         The old implementation used to 'bind' afslogon.dll to the credentials manager
223         when the Integrated Logon was selected.
224
225         With version 1.2.2a afslogon.dll is always 'bound' to the credentials manager; therefore,
226         the binding operation is done during installation.  Note: the Integrated Logon is
227         selected by an entry in the registry (LogonOptions).
228 */
229 void Config_GetAuthentFlag (BOOL *pfFlag)
230 {
231    *pfFlag = FALSE;
232
233    HKEY hk;
234    if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Control\\NetworkProvider\\Order"), 0, KEY_QUERY_VALUE, &hk) == ERROR_SUCCESS)
235       {
236       if (g.fIsWinNT)
237          {
238          TCHAR szProviders[ MAX_PATH ] = TEXT("");
239          DWORD dwSize = sizeof(szProviders);
240
241          if (RegQueryValueEx (hk, TEXT("ProviderOrder"), NULL, NULL, (PBYTE)szProviders, &dwSize) == ERROR_SUCCESS)
242             {
243             for (LPTSTR pch = szProviders; *pch; )
244                {
245                if (!lstrncmpi (pch, TEXT("TransarcAFSDaemon"), lstrlen(TEXT("TransarcAFSDaemon"))))
246                   *pfFlag = TRUE;
247
248                for ( ; *pch && (*pch != TEXT(',')); ++pch)
249                   ;
250                for ( ; *pch == TEXT(','); ++pch)
251                   ;
252                }
253             }
254
255          RegCloseKey (hk);
256          }
257       else // (!g.fIsWinNT)
258          {
259          TCHAR szLHS[ MAX_PATH ] = TEXT("");
260          DWORD dwSize = sizeof(szLHS);
261
262          if (RegQueryValueEx (hk, TEXT("TransarcAFSDaemon"), NULL, NULL, (PBYTE)szLHS, &dwSize) == ERROR_SUCCESS)
263             *pfFlag = TRUE;
264          }
265       }
266 }
267
268
269 BOOL Config_SetAuthentFlag (BOOL fFlag, ULONG *pStatus)
270 {
271    ULONG status = 0;
272    BOOL rc = FALSE;
273
274    HKEY hk;
275    DWORD dwDisp;
276    if ((status = RegCreateKeyEx (HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Control\\NetworkProvider\\Order"), 0, TEXT("container"), 0, KEY_QUERY_VALUE | KEY_SET_VALUE, NULL, &hk, &dwDisp)) == ERROR_SUCCESS)
277       {
278       if (g.fIsWinNT)
279          {
280          TCHAR szOldProviders[ MAX_PATH ] = TEXT("");
281          TCHAR szNewProviders[ MAX_PATH ] = TEXT("");
282          DWORD dwSize = sizeof(szOldProviders);
283          RegQueryValueEx (hk, TEXT("ProviderOrder"), NULL, NULL, (PBYTE)szOldProviders, &dwSize);
284
285          for (LPTSTR pch = szOldProviders; *pch; )
286             {
287             BOOL fCopy = TRUE;
288             if (!lstrncmpi (pch, TEXT("TransarcAFSDaemon"), lstrlen(TEXT("TransarcAFSDaemon"))))
289                {
290                fCopy = fFlag;
291                fFlag = FALSE;
292                }
293
294             if (fCopy)
295                {
296                LPTSTR pchOut = &szNewProviders[ lstrlen(szNewProviders) ];
297                if (szNewProviders[0])
298                   *pchOut++ = TEXT(',');
299                for ( ; *pch && (*pch != TEXT(',')); )
300                   *pchOut++ = *pch++;
301                *pchOut = TEXT('\0');
302                }
303
304             for ( ; *pch && (*pch != TEXT(',')); ++pch)
305                ;
306             for ( ; *pch == TEXT(','); ++pch)
307                ;
308             }
309
310          if (fFlag)
311             {
312             if (szNewProviders[0])
313                lstrcat (szNewProviders, TEXT(","));
314             lstrcat (szNewProviders, TEXT("TransarcAFSDaemon"));
315             }
316
317          if ((status = RegSetValueEx (hk, TEXT("ProviderOrder"), NULL, REG_SZ, (PBYTE)szNewProviders, sizeof(TCHAR)*(1+lstrlen(szNewProviders)))) == ERROR_SUCCESS)
318             rc = TRUE;
319          }
320       else // (!g.fIsWinNT)
321          {
322          TCHAR szLHS[ cchRESOURCE ] = TEXT("TransarcAFSDaemon");
323          TCHAR szRHS[ cchRESOURCE ] = TEXT("");
324
325          if (fFlag)
326             {
327             if ((status = RegSetValueEx (hk, szLHS, NULL, REG_SZ, (PBYTE)szRHS, sizeof(TCHAR)*(lstrlen(szRHS)+1))) == 0)
328                rc = TRUE;
329             }
330          else
331             {
332             RegDeleteValue (hk, szLHS);
333             rc = TRUE;
334             }
335          }
336
337       RegCloseKey (hk);
338       }
339
340    if (pStatus && !rc)
341       *pStatus = status;
342    if (!rc)
343       Message (MB_ICONHAND, GetErrorTitle(), IDS_FAILCONFIG_AUTHENT, TEXT("%ld"), status);
344    return rc;
345 }
346 #endif
347
348 void Config_GetTrayIconFlag (BOOL *pfFlag)
349 {
350    if (!Config_ReadUserNum (TEXT("ShowTrayIcon"), (DWORD*)pfFlag))
351       *pfFlag = FALSE;
352 }
353
354
355 BOOL Config_SetTrayIconFlag (BOOL fFlag, ULONG *pStatus)
356 {
357    Config_WriteUserNum (TEXT("ShowTrayIcon"), fFlag);
358
359    HWND hSearch;
360    for (hSearch = GetWindow (GetDesktopWindow(), GW_CHILD);
361         hSearch && IsWindow(hSearch);
362         hSearch = GetWindow (hSearch, GW_HWNDNEXT))
363       {
364       TCHAR szClassName[ cchRESOURCE ];
365       if (GetClassName (hSearch, szClassName, cchRESOURCE))
366          {
367          if (!lstrcmpi (szClassName, TEXT("AfsCreds")))
368             break;
369          }
370       }
371
372    if (hSearch && IsWindow(hSearch))
373       {
374       UINT msgCheckTerminate = RegisterWindowMessage (TEXT("AfsCredsCheckTerminate"));
375       PostMessage (hSearch, msgCheckTerminate, 0, 0);
376       }
377    else if (fFlag && !(hSearch && IsWindow(hSearch)))
378       {
379       WinExec (TEXT("AfsCreds.exe /quiet"), SW_SHOW);
380       }
381
382    return TRUE;
383 }
384
385
386 PSERVERPREFS Config_GetServerPrefs (BOOL fVLServers)
387 {
388    PSERVERPREFS pPrefs = New (SERVERPREFS);
389    memset (pPrefs, 0x00, sizeof(SERVERPREFS));
390    pPrefs->fVLServers = fVLServers;
391
392    if (Config_GetServiceState() == SERVICE_RUNNING)
393       {
394       // We retrieve server prefs in batches--start that loop now.
395       //
396       size_t iOut = 0;
397       for (int iOffset = 0; ; )
398          {
399          cm_SPrefRequest_t InData;
400          memset (&InData, 0x00, sizeof(InData));
401          InData.offset = iOffset;
402          InData.flags = (pPrefs->fVLServers) ? CM_SPREF_VLONLY : 0;
403          InData.num_servers = cSERVERPREFS_CHUNK;
404
405          BYTE OutDataStorage[ sizeof(cm_SPrefInfo_t) + cSERVERPREFS_CHUNK * sizeof(cm_SPref_t) ];
406          memset (OutDataStorage, 0x00, sizeof(OutDataStorage));
407          cm_SPrefInfo_t *pOutData = (cm_SPrefInfo_t *)OutDataStorage;
408
409          struct ViceIoctl IOInfo;
410          IOInfo.in_size = sizeof(InData);
411          IOInfo.in = (char *)&InData;
412          IOInfo.out = (char *)pOutData;
413          IOInfo.out_size = sizeof(cm_SPrefInfo_t) + cSERVERPREFS_CHUNK * sizeof(cm_SPref_t);
414
415          if (pioctl (0, VIOC_GETSPREFS, &IOInfo, 1) != 0)
416             break;
417
418          if (!REALLOC (pPrefs->aPrefs, pPrefs->cPrefs, iOut + pOutData->num_servers, cREALLOC_PREFS))
419             break;
420
421          for (size_t ii = 0; ii < pOutData->num_servers; ++ii)
422             {
423             pPrefs->aPrefs[ iOut ].ipServer = pOutData->servers[ ii ].host.s_addr;
424             pPrefs->aPrefs[ iOut ].iRank = pOutData->servers[ ii ].rank;
425             iOut ++;
426             }
427
428          if ((iOffset = pOutData->next_offset) == 0)
429             break;
430          }
431      }
432
433    return pPrefs;
434 }
435
436
437 BOOL Config_SetServerPrefs (PSERVERPREFS pPrefs, ULONG *pStatus)
438 {
439    BOOL rc = TRUE;
440    ULONG status = 0;
441
442    if (pPrefs)
443       {
444       size_t cChanged = 0;
445       size_t ii;
446       for (ii = 0; ii < pPrefs->cPrefs; ++ii)
447          {
448          if (pPrefs->aPrefs[ ii ].fChanged)
449             ++cChanged;
450          }
451
452       if (cChanged)
453          {
454          if (Config_GetServiceState() != SERVICE_RUNNING)
455             {
456             rc = FALSE;
457             status = ERROR_SERVICE_NOT_ACTIVE;
458             }
459          else
460             {
461             size_t cbInDataStorage = sizeof(cm_SSetPref_t) + cChanged * sizeof(cm_SPref_t);
462
463             PBYTE pInDataStorage;
464             if ((pInDataStorage = (PBYTE)Allocate (cbInDataStorage)) == NULL)
465                {
466                rc = FALSE;
467                status = ERROR_NOT_ENOUGH_MEMORY;
468                }
469             else
470                {
471                memset (pInDataStorage, 0x00, sizeof(cbInDataStorage));
472
473                cm_SSetPref_t *pInData = (cm_SSetPref_t*)pInDataStorage;
474                pInData->flags = (pPrefs->fVLServers) ? CM_SPREF_VLONLY : 0;
475                pInData->num_servers = cChanged;
476
477                size_t iOut = 0;
478                for (ii = 0; ii < pPrefs->cPrefs; ++ii)
479                   {
480                   if (pPrefs->aPrefs[ ii ].fChanged)
481                      {
482                      pInData->servers[ iOut ].host.s_addr = pPrefs->aPrefs[ ii ].ipServer;
483                      pInData->servers[ iOut ].rank = (unsigned short)pPrefs->aPrefs[ ii ].iRank;
484                      iOut++;
485                      }
486                   }
487
488                BYTE OutDataStorage[ PIOCTL_MAXSIZE ];
489
490                struct ViceIoctl IOInfo;
491                IOInfo.in_size = cbInDataStorage;
492                IOInfo.in = (char *)pInData;
493                IOInfo.out = (char *)OutDataStorage;
494                IOInfo.out_size = PIOCTL_MAXSIZE;
495
496                if ((status = pioctl (0, VIOC_SETSPREFS, &IOInfo, 1)) != 0)
497                   {
498                   rc = FALSE;
499                   }
500
501                Free (pInDataStorage);
502                }
503             }
504          }
505       }
506
507    if (pStatus && !rc)
508       *pStatus = status;
509    if (!rc)
510       Message (MB_ICONHAND, GetErrorTitle(), IDS_FAILCONFIG_PREFS, TEXT("%ld"), status);
511    return rc;
512 }
513
514
515 void Config_FreeServerPrefs (PSERVERPREFS pPrefs)
516 {
517    if (pPrefs->aPrefs)
518       Free (pPrefs->aPrefs);
519    memset (pPrefs, 0xFD, sizeof(SERVERPREFS));
520    Delete (pPrefs);
521 }
522
523
524 void Config_GetCacheSize (ULONG *pckCache)
525 {
526     if (!Config_ReadGlobalNum (TEXT("CacheSize"), (DWORD*)pckCache))
527         *pckCache = CM_CONFIGDEFAULT_CACHESIZE;
528 }
529
530
531 BOOL Config_SetCacheSize (ULONG ckCache, ULONG *pStatus)
532 {
533     Config_WriteGlobalNum (TEXT("CacheSize"), ckCache);
534     g.fNeedRestart = TRUE;
535     return TRUE;
536 }
537
538
539
540 void Config_GetChunkSize (ULONG *pckChunk)
541 {
542     if (!Config_ReadGlobalNum (TEXT("ChunkSize"), (DWORD*)pckChunk))
543         *pckChunk = CM_CONFIGDEFAULT_CHUNKSIZE;
544     *pckChunk = max (*pckChunk, 10);
545     *pckChunk = (1 << ((*pckChunk)-10));
546 }
547
548
549 BOOL Config_SetChunkSize (ULONG ckChunk, ULONG *pStatus)
550 {
551     Config_WriteGlobalNum (TEXT("ChunkSize"), log2(ckChunk * 1024));
552     g.fNeedRestart = TRUE;
553     return TRUE;
554 }
555
556
557
558 void Config_GetStatEntries (ULONG *pcEntries)
559 {
560     if (!Config_ReadGlobalNum (TEXT("Stats"), (DWORD*)pcEntries))
561         *pcEntries = CM_CONFIGDEFAULT_STATS;
562 }
563
564
565 BOOL Config_SetStatEntries (ULONG cEntries, ULONG *pStatus)
566 {
567     Config_WriteGlobalNum (TEXT("Stats"), cEntries);
568     g.fNeedRestart = TRUE;
569     return TRUE;
570 }
571
572
573
574 void Config_GetProbeInt (ULONG *pcsecProbe)
575 {
576     *pcsecProbe = 30;
577     // TODO: NEED REGISTRY SETTING
578 }
579
580
581 BOOL Config_SetProbeInt (ULONG csecProbe, ULONG *pStatus)
582 {
583     BOOL rc = TRUE;
584     ULONG status = 0;
585
586     // TODO: NEED REGISTRY SETTING
587     if (Config_GetServiceState() == SERVICE_RUNNING)
588     {
589         struct chservinfo checkserv;
590         memset (&checkserv, 0x00, sizeof(checkserv));
591         checkserv.magic = 0x12345678;
592         checkserv.tinterval = csecProbe;
593
594         BYTE OutData[ PIOCTL_MAXSIZE ];
595         memset (OutData, 0x00, sizeof(OutData));
596
597         struct ViceIoctl IOInfo;
598         IOInfo.in_size = sizeof(checkserv);
599         IOInfo.in = (char *)&checkserv;
600         IOInfo.out = (char *)OutData;
601         IOInfo.out_size = PIOCTL_MAXSIZE;
602
603         if ((status = pioctl (0, VIOCCKSERV, &IOInfo, 1)) != 0)
604         {
605             rc = FALSE;
606         }
607     }
608
609     if (pStatus && !rc)
610         *pStatus = status;
611     if (!rc)
612         Message (MB_ICONHAND, GetErrorTitle(), IDS_FAILCONFIG_PROBE, TEXT("%ld"), status);
613     return rc;
614 }
615
616
617
618 void Config_GetNumThreads (ULONG *pcThreads)
619 {
620     if (!Config_ReadGlobalNum (TEXT("ServerThreads"), (DWORD*)pcThreads))
621         *pcThreads = CM_CONFIGDEFAULT_SVTHREADS;
622 }
623
624
625 BOOL Config_SetNumThreads (ULONG cThreads, ULONG *pStatus)
626 {
627     Config_WriteGlobalNum (TEXT("ServerThreads"), cThreads);
628     g.fNeedRestart = TRUE;
629     return TRUE;
630 }
631
632
633
634 void Config_GetNumDaemons (ULONG *pcDaemons)
635 {
636     if (!Config_ReadGlobalNum (TEXT("Daemons"), (DWORD*)pcDaemons))
637         *pcDaemons = CM_CONFIGDEFAULT_DAEMONS;
638 }
639
640
641 BOOL Config_SetNumDaemons (ULONG cDaemons, ULONG *pStatus)
642 {
643     Config_WriteGlobalNum (TEXT("Daemons"), cDaemons);
644     g.fNeedRestart = TRUE;
645     return TRUE;
646 }
647
648
649
650 void Config_GetSysName (LPTSTR pszName)
651 {
652     if (!Config_ReadGlobalString (TEXT("SysName"), pszName, MAX_PATH))
653         lstrcpy (pszName, TEXT("i386_nt40"));
654 }
655
656
657 BOOL Config_SetSysName (LPCTSTR pszName, ULONG *pStatus)
658 {
659     BOOL rc = TRUE;
660     ULONG status = 0;
661
662     if (Config_GetServiceState() == SERVICE_RUNNING)
663     {
664         struct {
665             ULONG cbData;
666             TCHAR szData[ PIOCTL_MAXSIZE ];
667         } InData;
668         memset (&InData, 0x00, sizeof(InData));
669         USHORT i=0, j=0, len=lstrlen(pszName);
670
671         if ( len == 0 ) {
672             Message (MB_ICONHAND, GetErrorTitle(), IDS_FAILCONFIG_SYSNAME, TEXT("A sysname must be specified"));
673             return(-1);
674         }
675
676         while ( pszName[i] ) {
677             if ( !isspace(pszName[i]) ) {
678                 InData.szData[j++] = pszName[i];
679             } else if (InData.szData[j-1] != '\0') {
680                 InData.szData[j++] = '\0';
681                 InData.cbData++;
682             }
683             i++;
684         }
685         InData.szData[j++] = '\0';
686         InData.cbData++;      /* one word */
687
688         BYTE OutData[ PIOCTL_MAXSIZE ];
689         memset (OutData, 0x00, sizeof(OutData));
690
691         struct ViceIoctl IOInfo;
692         IOInfo.in_size = sizeof(ULONG) + j;
693         IOInfo.in = (char *)&InData;
694         IOInfo.out = (char *)OutData;
695         IOInfo.out_size = PIOCTL_MAXSIZE;
696
697         if ((status = pioctl (0, VIOC_AFS_SYSNAME, &IOInfo, 1)) != 0)
698         {
699             rc = FALSE;
700         }
701     }
702
703     if (rc)
704     {
705         Config_WriteGlobalString (TEXT("SysName"), pszName);
706     }
707
708     if (pStatus && !rc)
709         *pStatus = status;
710     if (!rc)
711         Message (MB_ICONHAND, GetErrorTitle(), IDS_FAILCONFIG_SYSNAME, TEXT("%ld"), status);
712     return rc;
713 }
714
715
716
717 void Config_GetRootVolume (LPTSTR pszName)
718 {
719     if (!Config_ReadGlobalString (TEXT("RootVolume"), pszName, MAX_PATH))
720         lstrcpy (pszName, TEXT("root.afs"));
721 }
722
723
724 BOOL Config_SetRootVolume (LPCTSTR pszName, ULONG *pStatus)
725 {
726     Config_WriteGlobalString (TEXT("RootVolume"), pszName);
727     g.fNeedRestart = TRUE;
728     return TRUE;
729 }
730
731
732
733 void Config_GetMountRoot (LPTSTR pszPath)
734 {
735     if (!Config_ReadGlobalString (TEXT("MountRoot"), pszPath, MAX_PATH))
736         lstrcpy (pszPath, TEXT("/afs"));
737 }
738
739
740 BOOL Config_SetMountRoot (LPCTSTR pszPath, ULONG *pStatus)
741 {
742     Config_WriteGlobalString (TEXT("MountRoot"), pszPath);
743     g.fNeedRestart = TRUE;
744     return TRUE;
745 }
746
747
748 BOOL Config_GetCacheInUse (ULONG *pckCacheInUse, ULONG *pStatus)
749 {
750     BOOL rc = TRUE;
751     ULONG status = 0;
752
753     *pckCacheInUse = 0;
754
755     if (Config_GetServiceState() != SERVICE_RUNNING)
756     {
757         rc = FALSE;
758         status = ERROR_SERVICE_NOT_ACTIVE;
759     }
760     else
761     {
762         BYTE OutData[ PIOCTL_MAXSIZE ];
763         memset (OutData, 0x00, sizeof(OutData));
764
765         struct ViceIoctl IOInfo;
766         IOInfo.in_size = 0;
767         IOInfo.in = (char *)0;
768         IOInfo.out = (char *)OutData;
769         IOInfo.out_size = PIOCTL_MAXSIZE;
770
771         if ((status = pioctl (0, VIOCGETCACHEPARMS, &IOInfo, 1)) != 0)
772         {
773             rc = FALSE;
774         }
775         else
776         {
777             *pckCacheInUse = ((LONG*)OutData)[1];
778         }
779     }
780
781     if (pStatus && !rc)
782         *pStatus = status;
783     return rc;
784 }
785
786 void Config_GetCachePath (LPTSTR pszCachePath)
787 {
788     if (!Config_ReadGlobalString (TEXT("CachePath"), pszCachePath, MAX_PATH)) {
789         HKEY hk;
790         TCHAR szPath[ MAX_PATH ] = TEXT("");
791
792         if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Control\\Session Manager\\Environment"), 0, KEY_QUERY_VALUE, &hk) == ERROR_SUCCESS)
793         {
794             DWORD dwSize = sizeof(szPath);
795             DWORD dwType = 0;
796
797             if (RegQueryValueEx (hk, TEXT("TEMP"), NULL, &dwType, (PBYTE)szPath, &dwSize) == ERROR_SUCCESS)
798             {
799                 if ( dwType == REG_EXPAND_SZ ) {
800                     TCHAR szTemp[ MAX_PATH ];
801                     lstrcpy(szTemp, szPath);
802                     ExpandEnvironmentStrings(szTemp, szPath, MAX_PATH);
803                 }
804             }
805             RegCloseKey (hk);
806             lstrcat(szPath, "\\AFSCache");
807         }
808
809         if ( !szPath[0] ) {
810             GetWindowsDirectory(szPath, sizeof(szPath));
811             lstrcat(szPath, "\\TEMP\\AFSCache");
812         }
813         lstrcpy (pszCachePath, szPath);
814     }
815 }
816
817 BOOL Config_SetCachePath(LPCTSTR pszPath, ULONG *pStatus)
818 {
819     Config_WriteGlobalString (TEXT("CachePath"), pszPath);
820     g.fNeedRestart = TRUE;
821     return TRUE;
822 }
823
824 void Config_GetLanAdapter (ULONG *pnLanAdapter)
825 {
826     if (!Config_ReadGlobalNum (TEXT("LANadapter"), (DWORD*)pnLanAdapter))
827         *pnLanAdapter = -1;
828 }
829
830 BOOL Config_SetLanAdapter (ULONG nLanAdapter, ULONG *pStatus)
831 {
832     Config_WriteGlobalNum (TEXT("LANadapter"), nLanAdapter);
833     g.fNeedRestart = TRUE;
834     return TRUE;
835 }
836
837 void Config_GetTrapOnPanic (BOOL *pfFlag)
838 {
839     if (!Config_ReadGlobalNum (TEXT("TrapOnPanic"), (DWORD*)pfFlag))
840         *pfFlag = TRUE;
841 }
842
843 BOOL Config_SetTrapOnPanic (BOOL fFlag, ULONG *pStatus)
844 {
845     Config_WriteGlobalNum (TEXT("TrapOnPanic"), fFlag);
846     g.fNeedRestart = TRUE;
847     return TRUE;
848 }
849
850 void Config_GetTraceBufferSize (ULONG *pnBufSize)
851 {
852     if (!Config_ReadGlobalNum (TEXT("TraceBufferSize"), (DWORD*)pnBufSize))
853         *pnBufSize = 5000;
854 }
855
856 BOOL Config_SetTraceBufferSize (ULONG nBufSize, ULONG *pStatus)
857 {
858     Config_WriteGlobalNum (TEXT("TraceBufferSize"), nBufSize);
859     g.fNeedRestart = TRUE;
860     return TRUE;
861 }
862
863 void Config_GetLoginRetryInterval (ULONG *pnInterval)
864 {
865     if (!Config_ReadGlobalNum (TEXT("LoginRetryInterval"), (DWORD*)pnInterval))
866         *pnInterval = 30;
867 }
868
869 BOOL Config_SetLoginRetryInterval (ULONG nInterval, ULONG *pStatus)
870 {
871     Config_WriteGlobalNum (TEXT("LoginRetryInterval"), nInterval);
872     return TRUE;
873 }
874
875 void Config_GetFailLoginsSilently (BOOL *pfFlag)
876 {
877     if (!Config_ReadGlobalNum (TEXT("FailLoginsSilently"), (DWORD*)pfFlag))
878         *pfFlag = FALSE;
879 }
880
881 BOOL Config_SetFailLoginsSilently (BOOL fFlag, ULONG *pStatus)
882 {
883     Config_WriteGlobalNum (TEXT("FailLoginsSilently"), fFlag);
884     return TRUE;
885 }
886
887 void Config_GetReportSessionStartups (BOOL *pfFlag)
888 {
889     if (!Config_ReadGlobalNum (TEXT("ReportSessionStartups"), (DWORD*)pfFlag))
890         *pfFlag = FALSE;
891 }
892
893 BOOL Config_SetReportSessionStartups (BOOL fFlag, ULONG *pStatus)
894 {
895     Config_WriteGlobalNum (TEXT("ReportSessionStartups"), fFlag);
896     return TRUE;
897 }
898