2 * Copyright 2000, International Business Machines Corporation and others.
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
11 #include <afs/param.h>
15 #include "afs_config.h"
19 #include "../afsd/fs_utils.h"
21 #define __CM_CONFIG_INTERFACES_ONLY__
22 #include "../afsd/cm_config.h"
24 #define __CM_IOCTL_INTERFACES_ONLY__
25 #include "../afsd/cm_ioctl.h"
30 #define cREALLOC_PREFS 32
32 #define cSERVERPREFS_CHUNK 256
34 #define PIOCTL_MAXSIZE 2048
39 * ROUTINES ___________________________________________________________________
43 static DWORD log2 (DWORD dwValue)
45 for (DWORD dwLog = 0; (DWORD)(1<<dwLog) < dwValue; ++dwLog)
50 DWORD Config_GetServiceState (void)
54 TCHAR szGateway[ cchRESOURCE ] = TEXT("");
55 Config_GetGatewayName (szGateway);
56 return (szGateway[0]) ? SERVICE_RUNNING : SERVICE_STOPPED;
59 SERVICE_STATUS Status;
60 memset (&Status, 0x00, sizeof(Status));
63 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
66 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
68 QueryServiceStatus (hService, &Status);
69 CloseServiceHandle (hService);
72 CloseServiceHandle (hManager);
75 return Status.dwCurrentState;
80 * Configuration Routine ______________________________________________________
84 void Config_GetGatewayFlag (BOOL *pfFlag)
86 if (!Config_ReadGlobalNum (TEXT("IsGateway"), (DWORD*)pfFlag))
91 BOOL Config_SetGatewayFlag (BOOL fFlag, ULONG *pStatus)
93 Config_WriteGlobalNum (TEXT("IsGateway"), fFlag);
94 g.fNeedRestart = TRUE;
99 void Config_GetGatewayName (LPTSTR pszName)
101 if (!Config_ReadGlobalString (TEXT("Gateway"), pszName, MAX_PATH))
102 GetString (pszName, IDS_GATEWAY_UNKNOWN);
104 GetString (pszName, IDS_GATEWAY_UNKNOWN);
108 BOOL Config_SetGatewayName (LPCTSTR pszName, ULONG *pStatus)
110 TCHAR szBogus[ cchRESOURCE ];
111 GetString (szBogus, IDS_GATEWAY_UNKNOWN);
112 if (!lstrcmpi (szBogus, pszName))
114 Config_WriteGlobalString (TEXT("Gateway"), TEXT(""));
118 Config_WriteGlobalString (TEXT("Gateway"), pszName);
125 void Config_FixGatewayDrives (void)
127 // Zip through the user's network drives and reconnect
128 // them as necessary.
130 for (TCHAR chDrive = chDRIVE_A; chDrive <= chDRIVE_Z; ++chDrive)
132 TCHAR szSubmount[ MAX_PATH ];
133 if (!GetDriveSubmount (chDrive, szSubmount))
136 // We've got a mapping into AFS! Remove it, rather forcefully.
138 TCHAR szDrive[] = "@:";
139 szDrive[0] = chDrive;
140 WNetCancelConnection (szDrive, TRUE);
143 // Now recreate our drive mappings, based on the user's already-
144 // specified preferences.
147 QueryDriveMapList (&List);
149 for (size_t ii = 0; ii < 26; ++ii)
151 if (!List.aDriveMap[ii].szMapping[0])
153 ActivateDriveMap (List.aDriveMap[ii].chDrive, List.aDriveMap[ii].szMapping, List.aDriveMap[ii].szSubmount, List.aDriveMap[ii].fPersistent);
158 void Config_GetCellName (LPTSTR pszName)
160 if (!Config_ReadGlobalString (TEXT("Cell"), pszName, MAX_PATH))
161 GetString (pszName, IDS_CELL_UNKNOWN);
163 GetString (pszName, IDS_CELL_UNKNOWN);
167 BOOL Config_ContactGateway (LPTSTR pszGateway, LPTSTR pszCell)
171 BYTE OutData[ PIOCTL_MAXSIZE ];
172 memset (OutData, 0x00, sizeof(OutData));
174 struct ViceIoctl IOInfo;
177 IOInfo.out = (char *)OutData;
178 IOInfo.out_size = PIOCTL_MAXSIZE;
180 TCHAR szOldGateway[ MAX_PATH ];
181 Config_GetGatewayName (szOldGateway);
182 Config_SetGatewayName (pszGateway);
185 if ((status = pioctl (0, VIOC_GET_WS_CELL, &IOInfo, 1)) == 0)
189 lstrcpy (pszCell, (LPCTSTR)OutData);
194 Config_SetGatewayName (szOldGateway);
200 BOOL Config_SetCellName (LPCTSTR pszName, ULONG *pStatus)
202 TCHAR szBogus[ cchRESOURCE ];
203 GetString (szBogus, IDS_CELL_UNKNOWN);
204 if (lstrcmpi (szBogus, pszName))
206 Config_WriteGlobalString (TEXT("Cell"), pszName);
207 g.fNeedRestart = TRUE;
213 /* These two functions are not needed as of the 1.2.2a updates.
214 The old implementation used to 'bind' afslogon.dll to the credentials manager
215 when the Integrated Logon was selected.
217 With version 1.2.2a afslogon.dll is always 'bound' to the credentials manager; therefore,
218 the binding operation is done during installation. Note: the Integrated Logon is
219 selected by an entry in the registry (LogonOptions).
221 void Config_GetAuthentFlag (BOOL *pfFlag)
226 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Control\\NetworkProvider\\Order"), 0, KEY_QUERY_VALUE, &hk) == ERROR_SUCCESS)
230 TCHAR szProviders[ MAX_PATH ] = TEXT("");
231 DWORD dwSize = sizeof(szProviders);
233 if (RegQueryValueEx (hk, TEXT("ProviderOrder"), NULL, NULL, (PBYTE)szProviders, &dwSize) == ERROR_SUCCESS)
235 for (LPTSTR pch = szProviders; *pch; )
237 if (!lstrncmpi (pch, TEXT("TransarcAFSDaemon"), lstrlen(TEXT("TransarcAFSDaemon"))))
240 for ( ; *pch && (*pch != TEXT(',')); ++pch)
242 for ( ; *pch == TEXT(','); ++pch)
249 else // (!g.fIsWinNT)
251 TCHAR szLHS[ MAX_PATH ] = TEXT("");
252 DWORD dwSize = sizeof(szLHS);
254 if (RegQueryValueEx (hk, TEXT("TransarcAFSDaemon"), NULL, NULL, (PBYTE)szLHS, &dwSize) == ERROR_SUCCESS)
261 BOOL Config_SetAuthentFlag (BOOL fFlag, ULONG *pStatus)
268 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)
272 TCHAR szOldProviders[ MAX_PATH ] = TEXT("");
273 TCHAR szNewProviders[ MAX_PATH ] = TEXT("");
274 DWORD dwSize = sizeof(szOldProviders);
275 RegQueryValueEx (hk, TEXT("ProviderOrder"), NULL, NULL, (PBYTE)szOldProviders, &dwSize);
277 for (LPTSTR pch = szOldProviders; *pch; )
280 if (!lstrncmpi (pch, TEXT("TransarcAFSDaemon"), lstrlen(TEXT("TransarcAFSDaemon"))))
288 LPTSTR pchOut = &szNewProviders[ lstrlen(szNewProviders) ];
289 if (szNewProviders[0])
290 *pchOut++ = TEXT(',');
291 for ( ; *pch && (*pch != TEXT(',')); )
293 *pchOut = TEXT('\0');
296 for ( ; *pch && (*pch != TEXT(',')); ++pch)
298 for ( ; *pch == TEXT(','); ++pch)
304 if (szNewProviders[0])
305 lstrcat (szNewProviders, TEXT(","));
306 lstrcat (szNewProviders, TEXT("TransarcAFSDaemon"));
309 if ((status = RegSetValueEx (hk, TEXT("ProviderOrder"), NULL, REG_SZ, (PBYTE)szNewProviders, sizeof(TCHAR)*(1+lstrlen(szNewProviders)))) == ERROR_SUCCESS)
312 else // (!g.fIsWinNT)
314 TCHAR szLHS[ cchRESOURCE ] = TEXT("TransarcAFSDaemon");
315 TCHAR szRHS[ cchRESOURCE ] = TEXT("");
319 if ((status = RegSetValueEx (hk, szLHS, NULL, REG_SZ, (PBYTE)szRHS, sizeof(TCHAR)*(lstrlen(szRHS)+1))) == 0)
324 RegDeleteValue (hk, szLHS);
335 Message (MB_ICONHAND, GetErrorTitle(), IDS_FAILCONFIG_AUTHENT, TEXT("%ld"), status);
340 void Config_GetTrayIconFlag (BOOL *pfFlag)
342 if (!Config_ReadUserNum (TEXT("ShowTrayIcon"), (DWORD*)pfFlag))
347 BOOL Config_SetTrayIconFlag (BOOL fFlag, ULONG *pStatus)
349 Config_WriteUserNum (TEXT("ShowTrayIcon"), fFlag);
351 for (HWND hSearch = GetWindow (GetDesktopWindow(), GW_CHILD);
352 hSearch && IsWindow(hSearch);
353 hSearch = GetWindow (hSearch, GW_HWNDNEXT))
355 TCHAR szClassName[ cchRESOURCE ];
356 if (GetClassName (hSearch, szClassName, cchRESOURCE))
358 if (!lstrcmpi (szClassName, TEXT("AfsCreds")))
363 if (hSearch && IsWindow(hSearch))
365 UINT msgCheckTerminate = RegisterWindowMessage (TEXT("AfsCredsCheckTerminate"));
366 PostMessage (hSearch, msgCheckTerminate, 0, 0);
368 else if (fFlag && !(hSearch && IsWindow(hSearch)))
370 WinExec (TEXT("AfsCreds.exe /quiet"), SW_SHOW);
377 PSERVERPREFS Config_GetServerPrefs (BOOL fVLServers)
379 PSERVERPREFS pPrefs = New (SERVERPREFS);
380 memset (pPrefs, 0x00, sizeof(SERVERPREFS));
381 pPrefs->fVLServers = fVLServers;
383 if (Config_GetServiceState() == SERVICE_RUNNING)
385 // We retrieve server prefs in batches--start that loop now.
388 for (int iOffset = 0; ; )
390 cm_SPrefRequest_t InData;
391 memset (&InData, 0x00, sizeof(InData));
392 InData.offset = iOffset;
393 InData.flags = (pPrefs->fVLServers) ? CM_SPREF_VLONLY : 0;
394 InData.num_servers = cSERVERPREFS_CHUNK;
396 BYTE OutDataStorage[ sizeof(cm_SPrefInfo_t) + cSERVERPREFS_CHUNK * sizeof(cm_SPref_t) ];
397 memset (OutDataStorage, 0x00, sizeof(OutDataStorage));
398 cm_SPrefInfo_t *pOutData = (cm_SPrefInfo_t *)OutDataStorage;
400 struct ViceIoctl IOInfo;
401 IOInfo.in_size = sizeof(InData);
402 IOInfo.in = (char *)&InData;
403 IOInfo.out = (char *)pOutData;
404 IOInfo.out_size = sizeof(cm_SPrefInfo_t) + cSERVERPREFS_CHUNK * sizeof(cm_SPref_t);
406 if (pioctl (0, VIOC_GETSPREFS, &IOInfo, 1) != 0)
409 if (!REALLOC (pPrefs->aPrefs, pPrefs->cPrefs, iOut + pOutData->num_servers, cREALLOC_PREFS))
412 for (size_t ii = 0; ii < pOutData->num_servers; ++ii)
414 pPrefs->aPrefs[ iOut ].ipServer = pOutData->servers[ ii ].host.s_addr;
415 pPrefs->aPrefs[ iOut ].iRank = pOutData->servers[ ii ].rank;
419 if ((iOffset = pOutData->next_offset) == 0)
428 BOOL Config_SetServerPrefs (PSERVERPREFS pPrefs, ULONG *pStatus)
436 for (size_t ii = 0; ii < pPrefs->cPrefs; ++ii)
438 if (pPrefs->aPrefs[ ii ].fChanged)
444 if (Config_GetServiceState() != SERVICE_RUNNING)
447 status = ERROR_SERVICE_NOT_ACTIVE;
451 size_t cbInDataStorage = sizeof(cm_SSetPref_t) + cChanged * sizeof(cm_SPref_t);
453 PBYTE pInDataStorage;
454 if ((pInDataStorage = (PBYTE)Allocate (cbInDataStorage)) == NULL)
457 status = ERROR_NOT_ENOUGH_MEMORY;
461 memset (pInDataStorage, 0x00, sizeof(cbInDataStorage));
463 cm_SSetPref_t *pInData = (cm_SSetPref_t*)pInDataStorage;
464 pInData->flags = (pPrefs->fVLServers) ? CM_SPREF_VLONLY : 0;
465 pInData->num_servers = cChanged;
468 for (ii = 0; ii < pPrefs->cPrefs; ++ii)
470 if (pPrefs->aPrefs[ ii ].fChanged)
472 pInData->servers[ iOut ].host.s_addr = pPrefs->aPrefs[ ii ].ipServer;
473 pInData->servers[ iOut ].rank = (unsigned short)pPrefs->aPrefs[ ii ].iRank;
478 BYTE OutDataStorage[ PIOCTL_MAXSIZE ];
480 struct ViceIoctl IOInfo;
481 IOInfo.in_size = cbInDataStorage;
482 IOInfo.in = (char *)pInData;
483 IOInfo.out = (char *)OutDataStorage;
484 IOInfo.out_size = PIOCTL_MAXSIZE;
486 if ((status = pioctl (0, VIOC_SETSPREFS, &IOInfo, 1)) != 0)
491 Free (pInDataStorage);
500 Message (MB_ICONHAND, GetErrorTitle(), IDS_FAILCONFIG_PREFS, TEXT("%ld"), status);
505 void Config_FreeServerPrefs (PSERVERPREFS pPrefs)
508 Free (pPrefs->aPrefs);
509 memset (pPrefs, 0xFD, sizeof(SERVERPREFS));
514 void Config_GetCacheSize (ULONG *pckCache)
516 if (!Config_ReadGlobalNum (TEXT("CacheSize"), (DWORD*)pckCache))
517 *pckCache = CM_CONFIGDEFAULT_CACHESIZE;
521 BOOL Config_SetCacheSize (ULONG ckCache, ULONG *pStatus)
526 if (Config_GetServiceState() == SERVICE_RUNNING)
529 Config_GetCacheSize (&ckCacheNow);
530 if (ckCacheNow > ckCache)
532 Message (MB_ICONHAND, GetErrorTitle(), IDS_SHRINKCACHE);
536 struct ViceIoctl IOInfo;
537 IOInfo.in_size = sizeof(ULONG);
538 IOInfo.in = (char *)&ckCache;
539 IOInfo.out = (char *)0;
542 if ((status = pioctl (0, VIOCSETCACHESIZE, &IOInfo, 1)) != 0)
550 Config_WriteGlobalNum (TEXT("CacheSize"), ckCache);
556 Message (MB_ICONHAND, GetErrorTitle(), IDS_FAILCONFIG_CACHE, TEXT("%ld"), status);
562 void Config_GetChunkSize (ULONG *pckChunk)
564 if (!Config_ReadGlobalNum (TEXT("ChunkSize"), (DWORD*)pckChunk))
565 *pckChunk = CM_CONFIGDEFAULT_CHUNKSIZE;
566 *pckChunk = max (*pckChunk, 10);
567 *pckChunk = (1 << ((*pckChunk)-10));
571 BOOL Config_SetChunkSize (ULONG ckChunk, ULONG *pStatus)
573 Config_WriteGlobalNum (TEXT("ChunkSize"), log2(ckChunk * 1024));
574 g.fNeedRestart = TRUE;
580 void Config_GetStatEntries (ULONG *pcEntries)
582 if (!Config_ReadGlobalNum (TEXT("Stats"), (DWORD*)pcEntries))
583 *pcEntries = CM_CONFIGDEFAULT_STATS;
587 BOOL Config_SetStatEntries (ULONG cEntries, ULONG *pStatus)
589 Config_WriteGlobalNum (TEXT("Stats"), cEntries);
590 g.fNeedRestart = TRUE;
596 void Config_GetProbeInt (ULONG *pcsecProbe)
599 // TODO: NEED REGISTRY SETTING
603 BOOL Config_SetProbeInt (ULONG csecProbe, ULONG *pStatus)
608 // TODO: NEED REGISTRY SETTING
609 if (Config_GetServiceState() == SERVICE_RUNNING)
611 struct chservinfo checkserv;
612 memset (&checkserv, 0x00, sizeof(checkserv));
613 checkserv.magic = 0x12345678;
614 checkserv.tinterval = csecProbe;
616 BYTE OutData[ PIOCTL_MAXSIZE ];
617 memset (OutData, 0x00, sizeof(OutData));
619 struct ViceIoctl IOInfo;
620 IOInfo.in_size = sizeof(checkserv);
621 IOInfo.in = (char *)&checkserv;
622 IOInfo.out = (char *)OutData;
623 IOInfo.out_size = PIOCTL_MAXSIZE;
625 if ((status = pioctl (0, VIOCCKSERV, &IOInfo, 1)) != 0)
634 Message (MB_ICONHAND, GetErrorTitle(), IDS_FAILCONFIG_PROBE, TEXT("%ld"), status);
640 void Config_GetNumThreads (ULONG *pcThreads)
642 if (!Config_ReadGlobalNum (TEXT("ServerThreads"), (DWORD*)pcThreads))
643 *pcThreads = CM_CONFIGDEFAULT_SVTHREADS;
647 BOOL Config_SetNumThreads (ULONG cThreads, ULONG *pStatus)
649 Config_WriteGlobalNum (TEXT("ServerThreads"), cThreads);
650 g.fNeedRestart = TRUE;
656 void Config_GetNumDaemons (ULONG *pcDaemons)
658 if (!Config_ReadGlobalNum (TEXT("Daemons"), (DWORD*)pcDaemons))
659 *pcDaemons = CM_CONFIGDEFAULT_DAEMONS;
663 BOOL Config_SetNumDaemons (ULONG cDaemons, ULONG *pStatus)
665 Config_WriteGlobalNum (TEXT("Daemons"), cDaemons);
666 g.fNeedRestart = TRUE;
672 void Config_GetSysName (LPTSTR pszName)
674 if (!Config_ReadGlobalString (TEXT("SysName"), pszName, MAX_PATH))
675 lstrcpy (pszName, TEXT("i386_nt40"));
679 BOOL Config_SetSysName (LPCTSTR pszName, ULONG *pStatus)
684 if (Config_GetServiceState() == SERVICE_RUNNING)
688 TCHAR szData[ PIOCTL_MAXSIZE ];
690 memset (&InData, 0x00, sizeof(InData));
691 InData.cbData = lstrlen(pszName);
692 lstrcpy (InData.szData, pszName);
694 BYTE OutData[ PIOCTL_MAXSIZE ];
695 memset (OutData, 0x00, sizeof(OutData));
697 struct ViceIoctl IOInfo;
698 IOInfo.in_size = sizeof(ULONG) +lstrlen(pszName) +1;
699 IOInfo.in = (char *)&InData;
700 IOInfo.out = (char *)OutData;
701 IOInfo.out_size = PIOCTL_MAXSIZE;
703 if ((status = pioctl (0, VIOC_AFS_SYSNAME, &IOInfo, 1)) != 0)
711 Config_WriteGlobalString (TEXT("SysName"), pszName);
717 Message (MB_ICONHAND, GetErrorTitle(), IDS_FAILCONFIG_SYSNAME, TEXT("%ld"), status);
723 void Config_GetRootVolume (LPTSTR pszName)
725 if (!Config_ReadGlobalString (TEXT("RootVolume"), pszName, MAX_PATH))
726 lstrcpy (pszName, TEXT("root.afs"));
730 BOOL Config_SetRootVolume (LPCTSTR pszName, ULONG *pStatus)
732 Config_WriteGlobalString (TEXT("RootVolume"), pszName);
733 g.fNeedRestart = TRUE;
739 void Config_GetMountRoot (LPTSTR pszPath)
741 if (!Config_ReadGlobalString (TEXT("MountRoot"), pszPath, MAX_PATH))
742 lstrcpy (pszPath, TEXT("/afs"));
746 BOOL Config_SetMountRoot (LPCTSTR pszPath, ULONG *pStatus)
748 Config_WriteGlobalString (TEXT("MountRoot"), pszPath);
749 g.fNeedRestart = TRUE;
754 BOOL Config_GetCacheInUse (ULONG *pckCacheInUse, ULONG *pStatus)
761 if (Config_GetServiceState() != SERVICE_RUNNING)
764 status = ERROR_SERVICE_NOT_ACTIVE;
768 BYTE OutData[ PIOCTL_MAXSIZE ];
769 memset (OutData, 0x00, sizeof(OutData));
771 struct ViceIoctl IOInfo;
773 IOInfo.in = (char *)0;
774 IOInfo.out = (char *)OutData;
775 IOInfo.out_size = PIOCTL_MAXSIZE;
777 if ((status = pioctl (0, VIOCGETCACHEPARMS, &IOInfo, 1)) != 0)
783 *pckCacheInUse = ((LONG*)OutData)[1];
792 void Config_GetCachePath (LPTSTR pszCachePath)
794 if (!Config_ReadGlobalString (TEXT("CachePath"), pszCachePath, MAX_PATH)) {
795 TCHAR szPath[MAX_PATH];
796 GetWindowsDirectory(szPath, sizeof(szPath));
797 szPath[2] = 0; /* get drive letter only */
798 strcat(szPath, "\\AFSCache");
800 lstrcpy (pszCachePath, szPath);
804 BOOL Config_SetCachePath(LPCTSTR pszPath, ULONG *pStatus)
806 Config_WriteGlobalString (TEXT("CachePath"), pszPath);
807 g.fNeedRestart = TRUE;
811 void Config_GetLanAdapter (ULONG *pnLanAdapter)
813 if (!Config_ReadGlobalNum (TEXT("LANadapter"), (DWORD*)pnLanAdapter))
817 BOOL Config_SetLanAdapter (ULONG nLanAdapter, ULONG *pStatus)
819 Config_WriteGlobalNum (TEXT("LANadapter"), nLanAdapter);
820 g.fNeedRestart = TRUE;
824 void Config_GetTrapOnPanic (BOOL *pfFlag)
826 if (!Config_ReadGlobalNum (TEXT("TrapOnPanic"), (DWORD*)pfFlag))
830 BOOL Config_SetTrapOnPanic (BOOL fFlag, ULONG *pStatus)
832 Config_WriteGlobalNum (TEXT("TrapOnPanic"), fFlag);
833 g.fNeedRestart = TRUE;
837 void Config_GetTraceBufferSize (ULONG *pnBufSize)
839 if (!Config_ReadGlobalNum (TEXT("TraceBufferSize"), (DWORD*)pnBufSize))
843 BOOL Config_SetTraceBufferSize (ULONG nBufSize, ULONG *pStatus)
845 Config_WriteGlobalNum (TEXT("TraceBufferSize"), nBufSize);
846 g.fNeedRestart = TRUE;
850 void Config_GetLoginRetryInterval (ULONG *pnInterval)
852 if (!Config_ReadGlobalNum (TEXT("LoginRetryInterval"), (DWORD*)pnInterval))
856 BOOL Config_SetLoginRetryInterval (ULONG nInterval, ULONG *pStatus)
858 Config_WriteGlobalNum (TEXT("LoginRetryInterval"), nInterval);
862 void Config_GetFailLoginsSilently (BOOL *pfFlag)
864 if (!Config_ReadGlobalNum (TEXT("FailLoginsSilently"), (DWORD*)pfFlag))
868 BOOL Config_SetFailLoginsSilently (BOOL fFlag, ULONG *pStatus)
870 Config_WriteGlobalNum (TEXT("FailLoginsSilently"), fFlag);
874 void Config_GetReportSessionStartups (BOOL *pfFlag)
876 if (!Config_ReadGlobalNum (TEXT("ReportSessionStartups"), (DWORD*)pfFlag))
880 BOOL Config_SetReportSessionStartups (BOOL fFlag, ULONG *pStatus)
882 Config_WriteGlobalNum (TEXT("ReportSessionStartups"), fFlag);