/* Copyright (c) 1995, Microsoft Corporation, all rights reserved ** ** pbuser.c ** User preference storage routines ** Listed alphabetically ** ** 10/31/95 Steve Cobb */ #include // Win32 root #include // Trace/Assert library #include // Heap macros #include // Our public header #include // RAS common dialog header for RASMD_* /* Default user preference settings. */ static const PBUSER g_pbuserDefaults = { FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, 0, 15, 1200, FALSE, TRUE, FALSE, CBM_Maybe, NULL, NULL, PBM_System, NULL, NULL, NULL, NULL, FALSE, NULL, NULL, NULL, 0x7FFFFFFF, 0x7FFFFFFF, NULL, FALSE, FALSE }; /*---------------------------------------------------------------------------- ** Local prototypes (alphabetically) **---------------------------------------------------------------------------- */ VOID GetCallbackList( IN HKEY hkey, OUT DTLLIST** ppListResult ); VOID GetLocationList( IN HKEY hkey, OUT DTLLIST** ppListResult ); VOID MoveLogonPreferences( void ); VOID MoveUserPreferences( void ); DWORD ReadUserPreferences( IN HKEY hkey, OUT PBUSER* pUser ); DWORD SetCallbackList( IN HKEY hkey, IN DTLLIST* pList ); DWORD SetDefaultUserPreferences( OUT PBUSER* pUser, IN DWORD dwMode ); DWORD SetLocationList( IN HKEY hkey, IN DTLLIST* pList ); DWORD WriteUserPreferences( IN HKEY hkey, IN PBUSER* pUser ); /*---------------------------------------------------------------------------- ** Phonebook preference routines (alphabetically) **---------------------------------------------------------------------------- */ DTLNODE* CreateLocationNode( IN DWORD dwLocationId, IN DWORD iPrefix, IN DWORD iSuffix ) /* Returns a LOCATIONINFO node associated with TAPI location ** 'dwLocationId', prefix index 'iPrefix' and suffix index 'iSuffix'. */ { DTLNODE* pNode; LOCATIONINFO* pInfo; pNode = DtlCreateSizedNode( sizeof(LOCATIONINFO), 0L ); if (!pNode) return NULL; pInfo = (LOCATIONINFO* )DtlGetData( pNode ); pInfo->dwLocationId = dwLocationId; pInfo->iPrefix = iPrefix; pInfo->iSuffix = iSuffix; return pNode; } DTLNODE* CreateCallbackNode( IN TCHAR* pszPortName, IN TCHAR* pszDeviceName, IN TCHAR* pszNumber, IN DWORD dwDeviceType ) /* Returns a CALLBACKINFO node containing a copy of 'pszPortName', ** 'pszDeviceName' and 'pszNumber' and 'dwDeviceType' or NULL on error. ** It is caller's responsibility to DestroyCallbackNode the returned node. */ { DTLNODE* pNode; CALLBACKINFO* pInfo; pNode = DtlCreateSizedNode( sizeof(CALLBACKINFO), 0L ); if (!pNode) return NULL; pInfo = (CALLBACKINFO* )DtlGetData( pNode ); pInfo->pszPortName = StrDup( pszPortName ); pInfo->pszDeviceName = StrDup( pszDeviceName ); pInfo->pszNumber = StrDup( pszNumber ); pInfo->dwDeviceType = dwDeviceType; if (!pInfo->pszPortName || !pInfo->pszDeviceName || !pInfo->pszNumber) { Free0( pInfo->pszPortName ); Free0( pInfo->pszDeviceName ); Free0( pInfo->pszNumber ); DtlDestroyNode( pNode ); return NULL; } return pNode; } VOID DestroyLocationNode( IN DTLNODE* pNode ) /* Release memory allociated with location node 'pNode'. */ { DtlDestroyNode( pNode ); } VOID DestroyCallbackNode( IN DTLNODE* pNode ) /* Release memory allociated with callback node 'pNode'. */ { CALLBACKINFO* pInfo; ASSERT(pNode); pInfo = (CALLBACKINFO* )DtlGetData( pNode ); ASSERT(pInfo); Free0( pInfo->pszPortName ); Free0( pInfo->pszDeviceName ); Free0( pInfo->pszNumber ); DtlDestroyNode( pNode ); } VOID DestroyUserPreferences( IN PBUSER* pUser ) /* Releases memory allocated by GetUserPreferences and zeros the ** structure. */ { if (pUser->fInitialized) { DtlDestroyList( pUser->pdtllistCallback, DestroyCallbackNode ); DtlDestroyList( pUser->pdtllistPhonebooks, DestroyPszNode ); DtlDestroyList( pUser->pdtllistAreaCodes, DestroyPszNode ); DtlDestroyList( pUser->pdtllistPrefixes, DestroyPszNode ); DtlDestroyList( pUser->pdtllistSuffixes, DestroyPszNode ); DtlDestroyList( pUser->pdtllistLocations, DestroyLocationNode ); Free0( pUser->pszPersonalFile ); Free0( pUser->pszAlternatePath ); Free0( pUser->pszLastCallbackByCaller ); Free0( pUser->pszDefaultEntry ); } ZeroMemory( pUser, sizeof(*pUser) ); } DTLNODE* DuplicateLocationNode( IN DTLNODE* pNode ) /* Duplicates LOCATIONINFO node 'pNode'. See DtlDuplicateList. ** ** Returns the address of the allocated node or NULL if out of memory. It ** is caller's responsibility to free the returned node. */ { LOCATIONINFO* pInfo = (LOCATIONINFO* )DtlGetData( pNode ); return CreateLocationNode( pInfo->dwLocationId, pInfo->iPrefix, pInfo->iSuffix ); } DWORD DwGetUserPreferences( OUT PBUSER* pUser, IN DWORD dwMode ) /* Load caller's 'pUser' with user phonebook preferences from the ** registry. 'DwMode' indicates the preferences to get, either the normal ** interactive user, the pre-logon, or router preferences. ** ** Returns 0 if successful or an error code. If successful, caller should ** eventually call DestroyUserPreferences to release the returned heap ** buffers. */ { DWORD dwErr; TRACE1("GetUserPreferences(m=%d)",dwMode); /* Move the user preferences, if it's not already been done. */ if (dwMode == UPM_Normal) MoveUserPreferences(); else if (dwMode == UPM_Logon) MoveLogonPreferences(); dwErr = SetDefaultUserPreferences( pUser, dwMode ); if (dwErr == 0) { HKEY hkey; DWORD dwErr2; if (dwMode == UPM_Normal) { dwErr2 = RegOpenKeyEx( HKEY_CURRENT_USER, (LPCTSTR )REGKEY_HkcuRas, 0, KEY_READ, &hkey ); } else if (dwMode == UPM_Logon) { dwErr2 = RegOpenKeyEx( HKEY_USERS, (LPCTSTR )REGKEY_HkuRasLogon, 0, KEY_READ, &hkey ); } else { ASSERT(dwMode==UPM_Router); dwErr2 = RegOpenKeyEx( HKEY_LOCAL_MACHINE, (LPCTSTR )REGKEY_HklmRouter, 0, KEY_READ, &hkey ); } if (dwErr2 == 0) { if (ReadUserPreferences( hkey, pUser ) != 0) dwErr = SetDefaultUserPreferences( pUser, dwMode ); RegCloseKey( hkey ); } else { TRACE1("RegOpenKeyEx=%d",dwErr2); } } TRACE1("GetUserPreferences=%d",dwErr); return dwErr; } DWORD GetUserPreferences(HANDLE hConnection, PBUSER *pUser, DWORD dwMode) { RAS_RPC *pRasRpcConnection = (RAS_RPC *) hConnection; DWORD dwError = ERROR_SUCCESS; if( NULL == pRasRpcConnection || pRasRpcConnection->fLocal) { dwError = DwGetUserPreferences(pUser, dwMode); } else { dwError = RemoteGetUserPreferences(hConnection, pUser, dwMode); } return dwError; } DWORD DwSetUserPreferences( IN PBUSER* pUser, IN DWORD dwMode ) /* Set current user phonebook preferences in the registry from caller's ** settings in 'pUser', if necessary. 'DwMode' indicates the preferences ** to get, either the normal interactive user, the pre-logon, or router ** preferences. ** ** Returns 0 if successful, or an error code. Caller's 'pUser' is marked ** clean if successful. */ { DWORD dwErr; DWORD dwDisposition; HKEY hkey; TRACE1("SetUserPreferences(m=%d)",dwMode); if (!pUser->fDirty) return 0; /* Create the preference key, or if it exists just open it. */ if (dwMode == UPM_Normal) { dwErr = RegCreateKeyEx( HKEY_CURRENT_USER, REGKEY_HkcuRas, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwDisposition ); } else if (dwMode == UPM_Logon) { dwErr = RegCreateKeyEx( HKEY_USERS, REGKEY_HkuRasLogon, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwDisposition ); } else { ASSERT(dwMode==UPM_Router); dwErr = RegCreateKeyEx( HKEY_LOCAL_MACHINE, REGKEY_HklmRouter, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwDisposition ); } if (dwErr == 0) { dwErr = WriteUserPreferences( hkey, pUser ); RegCloseKey( hkey ); } TRACE1("SetUserPreferences=%d",dwErr); return dwErr; } DWORD SetUserPreferences(HANDLE hConnection, PBUSER *pUser, DWORD dwMode) { DWORD dwError = ERROR_SUCCESS; RAS_RPC *pRasRpcConnection = (RAS_RPC *) hConnection; if( NULL == pRasRpcConnection || pRasRpcConnection->fLocal) { dwError = DwSetUserPreferences(pUser, dwMode); } else { dwError = RemoteSetUserPreferences(hConnection, pUser, dwMode); } return dwError; } // Reads the operator assisted dial user parameter directly from // the registry. DWORD SetUserManualDialEnabling ( IN OUT BOOL bEnable, IN DWORD dwMode ) { DWORD dwErr; DWORD dwDisposition; HKEY hkey; TRACE2("SetUserManualDialEnabling (en=%d) (m=%d)",bEnable, dwMode); /* Create the preference key, or if it exists just open it. */ if (dwMode == UPM_Normal) { dwErr = RegCreateKeyEx( HKEY_CURRENT_USER, REGKEY_HkcuRas, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwDisposition ); } else if (dwMode == UPM_Logon) { dwErr = RegCreateKeyEx( HKEY_USERS, REGKEY_HkuRasLogon, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwDisposition ); } else return ERROR_INVALID_PARAMETER; if (dwErr != 0) return dwErr; dwErr = SetRegDword( hkey, REGVAL_fOperatorDial, !!bEnable ); RegCloseKey( hkey ); return dwErr; } // Sets the operator assisted dialing parameter directly in the // registry. DWORD GetUserManualDialEnabling ( IN PBOOL pbEnabled, IN DWORD dwMode ) { DWORD dwErr; DWORD dwDisposition; HKEY hkey; TRACE1("GetUserManualDialEnabling (m=%d)", dwMode); if (!pbEnabled) return ERROR_INVALID_PARAMETER; // Set defaults *pbEnabled = g_pbuserDefaults.fOperatorDial; /* Create the preference key, or if it exists just open it. */ if (dwMode == UPM_Normal) { dwErr = RegCreateKeyEx( HKEY_CURRENT_USER, REGKEY_HkcuRas, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwDisposition ); } else if (dwMode == UPM_Logon) { dwErr = RegCreateKeyEx( HKEY_USERS, REGKEY_HkuRasLogon, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwDisposition ); } else return ERROR_INVALID_PARAMETER; if (dwErr != 0) return dwErr; GetRegDword( hkey, REGVAL_fOperatorDial, pbEnabled ); RegCloseKey( hkey ); return dwErr; } /*---------------------------------------------------------------------------- ** Utilities (alphabetically) **---------------------------------------------------------------------------- */ VOID GetCallbackList( IN HKEY hkey, OUT DTLLIST** ppListResult ) /* Replaces '*ppListResult' with a list containing a node for each device ** name under registry value "REGVAL_szCallback" of registry key 'hkey'. ** If no values exist *ppListResult' is replaced with an empty list. ** ** It is caller's responsibility to destroy the returned list if non-NULL. */ { DWORD dwErr; TCHAR szDP[ RAS_MaxDeviceName + 2 + MAX_PORT_NAME + 1 + 1 ]; TCHAR* pszDevice; TCHAR* pszPort; TCHAR* pszNumber; DWORD dwDeviceType; DWORD cb; INT i; DTLLIST* pList; DTLNODE* pNode; HKEY hkeyCb; HKEY hkeyDP; pList = DtlCreateList( 0 ); if (!pList) return; dwErr = RegOpenKeyEx( hkey, REGKEY_Callback, 0, KEY_READ, &hkeyCb ); if (dwErr == 0) { for (i = 0; TRUE; ++i) { cb = sizeof(szDP)/sizeof(TCHAR); dwErr = RegEnumKeyEx( hkeyCb, i, szDP, &cb, NULL, NULL, NULL, NULL ); if (dwErr == ERROR_NO_MORE_ITEMS) break; if (dwErr != 0) continue; /* Ignore keys not of the form "device (port)". */ if (!DeviceAndPortFromPsz( szDP, &pszDevice, &pszPort )) continue; dwErr = RegOpenKeyEx( hkeyCb, szDP, 0, KEY_READ, &hkeyDP ); if (dwErr == 0) { GetRegDword( hkeyDP, REGVAL_dwDeviceType, &dwDeviceType ); dwErr = GetRegSz( hkeyDP, REGVAL_szNumber, &pszNumber ); if (dwErr == 0) { pNode = CreateCallbackNode( pszPort, pszDevice, pszNumber, dwDeviceType ); if (pNode) DtlAddNodeLast( pList, pNode ); Free( pszNumber ); } RegCloseKey( hkeyDP ); } Free( pszDevice ); Free( pszPort ); } RegCloseKey( hkeyCb ); } DtlDestroyList( *ppListResult, DestroyCallbackNode ); *ppListResult = pList; } VOID GetLocationList( IN HKEY hkey, OUT DTLLIST** ppListResult ) /* Replaces '*ppListResult' with a list containing a node for each ** location under registry value "REGVAL_szLocation" of registry key ** 'hkey'. If no values exist *ppListResult' is replaced with an empty ** list. ** ** It is caller's responsibility to destroy the returned list if non-NULL. */ { DWORD dwErr; TCHAR szId[ MAXLTOTLEN + 1 ]; DWORD cb; INT i; DTLLIST* pList; DTLNODE* pNode; HKEY hkeyL; HKEY hkeyId; pList = DtlCreateList( 0 ); if (!pList) return; dwErr = RegOpenKeyEx( hkey, REGKEY_Location, 0, KEY_READ, &hkeyL ); if (dwErr == 0) { for (i = 0; TRUE; ++i) { cb = MAXLTOTLEN + 1; dwErr = RegEnumKeyEx( hkeyL, i, szId, &cb, NULL, NULL, NULL, NULL ); if (dwErr == ERROR_NO_MORE_ITEMS) break; if (dwErr != 0) continue; dwErr = RegOpenKeyEx( hkeyL, szId, 0, KEY_READ, &hkeyId ); if (dwErr == 0) { DWORD dwId; DWORD iPrefix; DWORD iSuffix; dwId = (DWORD )TToL( szId ); iPrefix = 0; GetRegDword( hkeyId, REGVAL_dwPrefix, &iPrefix ); iSuffix = 0; GetRegDword( hkeyId, REGVAL_dwSuffix, &iSuffix ); pNode = CreateLocationNode( dwId, iPrefix, iSuffix ); if (!pNode) continue; DtlAddNodeLast( pList, pNode ); RegCloseKey( hkeyId ); } } RegCloseKey( hkeyL ); } DtlDestroyList( *ppListResult, DestroyLocationNode ); *ppListResult = pList; } VOID MoveLogonPreferences( void ) /* Move logon preferences from the NT 4.0 location to a new unique ** position, if necessary. This manuever is added because in NT 4.0 user ** preference calls from LocalSystem service use the old logon location at ** HKU\.DEFAULT due to fallbacks in the registry APIs causing logon and ** LocalSystem settings to overwrite each other. */ { DWORD dwErr; HKEY hkeyOld; HKEY hkeyNew; PBUSER user; dwErr = RegOpenKeyEx( HKEY_USERS, (LPCTSTR )REGKEY_HkuOldRasLogon, 0, KEY_READ, &hkeyOld ); if (dwErr != 0) return; dwErr = RegOpenKeyEx( HKEY_USERS, (LPCTSTR )REGKEY_HkuRasLogon, 0, KEY_READ, &hkeyNew ); if (dwErr == 0) RegCloseKey( hkeyNew ); else { /* Old tree exists and new tree doesn't. Move a copy of the old tree ** to the new tree. */ dwErr = SetDefaultUserPreferences( &user, UPM_Logon ); if (dwErr == 0) { dwErr = ReadUserPreferences( hkeyOld, &user ); if (dwErr == 0) dwErr = SetUserPreferences( NULL, &user, UPM_Logon ); } DestroyUserPreferences( &user ); TRACE1("MoveLogonPreferences=%d",dwErr); } RegCloseKey( hkeyOld ); } VOID MoveUserPreferences( void ) /* Move user preferences from their old net-tools registry location to the ** new location nearer the other RAS keys. */ { DWORD dwErr; HKEY hkeyOld; HKEY hkeyNew; /* See if the old current-user key exists. */ dwErr = RegOpenKeyEx( HKEY_CURRENT_USER, (LPCTSTR )REGKEY_HkcuOldRas, 0, KEY_ALL_ACCESS, &hkeyOld ); if (dwErr == 0) { PBUSER user; /* Read the preferences at the old key. */ TRACE("Getting old prefs"); dwErr = SetDefaultUserPreferences( &user, UPM_Normal ); if (dwErr == 0) { dwErr = ReadUserPreferences( hkeyOld, &user ); if (dwErr == 0) { /* Write the preferences at the new key. */ user.fDirty = TRUE; dwErr = SetUserPreferences( NULL, &user, FALSE ); if (dwErr == 0) { /* Blow away the old tree. */ dwErr = RegOpenKeyEx( HKEY_CURRENT_USER, (LPCTSTR )REGKEY_HkcuOldRasParent, 0, KEY_ALL_ACCESS, &hkeyNew ); if (dwErr == 0) { TRACE("Delete old prefs"); dwErr = RegDeleteTree( hkeyNew, REGKEY_HkcuOldRasRoot ); RegCloseKey( hkeyNew ); } } } } RegCloseKey( hkeyOld ); TRACE1("MoveUserPreferences=%d",dwErr); } } DWORD ReadUserPreferences( IN HKEY hkey, OUT PBUSER* pUser ) /* Fill caller's 'pUser' buffer with user preferences from RAS-Phonebook ** registry tree 'hkey'. ** ** Returns 0 if successful, false otherwise. */ { BOOL fOldSettings; DWORD dwErr; TRACE("ReadUserPreferences"); /* Read the values. */ { DWORD dwMode; /* Lack of a phonebook mode key indicates that we are updating old NT ** 3.51-style settings. */ dwMode = 0xFFFFFFFF; GetRegDword( hkey, REGVAL_dwPhonebookMode, &dwMode ); if (dwMode != 0xFFFFFFFF) { pUser->dwPhonebookMode = dwMode; fOldSettings = FALSE; } else fOldSettings = TRUE; } GetRegDword( hkey, REGVAL_fOperatorDial, &pUser->fOperatorDial ); GetRegDword( hkey, REGVAL_fPreviewPhoneNumber, &pUser->fPreviewPhoneNumber ); GetRegDword( hkey, REGVAL_fUseLocation, &pUser->fUseLocation ); GetRegDword( hkey, REGVAL_fShowLights, &pUser->fShowLights ); GetRegDword( hkey, REGVAL_fShowConnectStatus, &pUser->fShowConnectStatus ); GetRegDword( hkey, REGVAL_fNewEntryWizard, &pUser->fNewEntryWizard ); GetRegDword( hkey, REGVAL_fCloseOnDial, &pUser->fCloseOnDial ); GetRegDword( hkey, REGVAL_fAllowLogonPhonebookEdits, &pUser->fAllowLogonPhonebookEdits ); GetRegDword( hkey, REGVAL_fAllowLogonLocationEdits, &pUser->fAllowLogonLocationEdits ); GetRegDword( hkey, REGVAL_fSkipConnectComplete, &pUser->fSkipConnectComplete ); GetRegDword( hkey, REGVAL_dwRedialAttempts, &pUser->dwRedialAttempts ); GetRegDword( hkey, REGVAL_dwRedialSeconds, &pUser->dwRedialSeconds ); GetRegDword( hkey, REGVAL_dwIdleDisconnectSeconds, &pUser->dwIdleDisconnectSeconds ); GetRegDword( hkey, REGVAL_fRedialOnLinkFailure, &pUser->fRedialOnLinkFailure ); GetRegDword( hkey, REGVAL_fPopupOnTopWhenRedialing, &pUser->fPopupOnTopWhenRedialing ); GetRegDword( hkey, REGVAL_fExpandAutoDialQuery, &pUser->fExpandAutoDialQuery ); GetRegDword( hkey, REGVAL_dwCallbackMode, &pUser->dwCallbackMode ); GetRegDword( hkey, REGVAL_fUseAreaAndCountry, &pUser->fUseAreaAndCountry ); GetRegDword( hkey, REGVAL_dwXWindow, &pUser->dwXPhonebook ); GetRegDword( hkey, REGVAL_dwYWindow, &pUser->dwYPhonebook ); // // For NT5, we ignore the "require wizard" setting since // we always require the user to use the wizard to create // new connections // pUser->fNewEntryWizard = TRUE; do { GetCallbackList( hkey, &pUser->pdtllistCallback ); dwErr = GetRegMultiSz( hkey, REGVAL_mszPhonebooks, &pUser->pdtllistPhonebooks, NT_Psz ); if (dwErr != 0) break; dwErr = GetRegMultiSz( hkey, REGVAL_mszAreaCodes, &pUser->pdtllistAreaCodes, NT_Psz ); if (dwErr != 0) break; /* If the prefixes key doesn't exist don't read an empty list over the ** defaults. */ if (RegValueExists( hkey, REGVAL_mszPrefixes )) { dwErr = GetRegMultiSz( hkey, REGVAL_mszPrefixes, &pUser->pdtllistPrefixes, NT_Psz ); if (dwErr != 0) break; } dwErr = GetRegMultiSz( hkey, REGVAL_mszSuffixes, &pUser->pdtllistSuffixes, NT_Psz ); if (dwErr != 0) break; GetLocationList( hkey, &pUser->pdtllistLocations ); dwErr = GetRegSz( hkey, REGVAL_szLastCallbackByCaller, &pUser->pszLastCallbackByCaller ); if (dwErr != 0) break; /* Get the personal phonebook file name, if any. In NT 3.51, the full ** path was stored, but now "\system32\ras" directory is assumed. ** This gives better (not perfect) behavior with user profiles rooted ** on different drive letters. */ { TCHAR* psz; dwErr = GetRegSz( hkey, REGVAL_szPersonalPhonebookPath, &psz ); if (dwErr != 0) break; if (*psz == TEXT('\0')) { Free(psz); dwErr = GetRegSz( hkey, REGVAL_szPersonalPhonebookFile, &pUser->pszPersonalFile ); if (dwErr != 0) break; } else { pUser->pszPersonalFile = StrDup( StripPath( psz ) ); Free( psz ); if (!pUser->pszPersonalFile) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; } } } dwErr = GetRegSz( hkey, REGVAL_szAlternatePhonebookPath, &pUser->pszAlternatePath ); if (dwErr != 0) break; dwErr = GetRegSz( hkey, REGVAL_szDefaultEntry, &pUser->pszDefaultEntry ); if (dwErr != 0) break; if (fOldSettings) { TCHAR* psz; psz = NULL; dwErr = GetRegSz( hkey, REGVAL_szUsePersonalPhonebook, &psz ); if (dwErr != 0) break; if (psz) { if (*psz == TEXT('1')) pUser->dwPhonebookMode = PBM_Personal; Free( psz ); } } } while (FALSE); if (dwErr != 0) DestroyUserPreferences( pUser ); TRACE1("ReadUserPreferences=%d",dwErr); return dwErr; } DWORD SetCallbackList( IN HKEY hkey, IN DTLLIST* pList ) /* Sets callback tree under registry key 'hkey' to the list of callback ** nodes 'pList'. ** ** Returns 0 if successful or an error code. */ { DWORD dwErr; TCHAR szDP[ RAS_MaxDeviceName + 2 + MAX_PORT_NAME + 1 + 1 ]; DWORD cb; DWORD i; DWORD dwDisposition; HKEY hkeyCb; HKEY hkeyDP; DTLNODE* pNode; dwErr = RegCreateKeyEx( hkey, REGKEY_Callback, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyCb, &dwDisposition ); if (dwErr != 0) return dwErr; /* Delete all keys and values under the callback key. */ for (;;) { cb = sizeof(szDP); dwErr = RegEnumKeyEx( hkeyCb, 0, szDP, &cb, NULL, NULL, NULL, NULL ); if (dwErr != 0) break; dwErr = RegDeleteKey( hkeyCb, szDP ); if (dwErr != 0) break; } if (dwErr == ERROR_NO_MORE_ITEMS) dwErr = 0; if (dwErr == 0) { /* Add the new device/port sub-trees. */ for (pNode = DtlGetFirstNode( pList ); pNode; pNode = DtlGetNextNode( pNode )) { CALLBACKINFO* pInfo; TCHAR* psz; pInfo = (CALLBACKINFO* )DtlGetData( pNode ); ASSERT(pInfo); ASSERT(pInfo->pszPortName); ASSERT(pInfo->pszDeviceName); ASSERT(pInfo->pszNumber); psz = PszFromDeviceAndPort( pInfo->pszDeviceName, pInfo->pszPortName ); if (psz) { dwErr = RegCreateKeyEx( hkeyCb, psz, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyDP, &dwDisposition ); if (dwErr != 0) break; dwErr = SetRegDword( hkeyDP, REGVAL_dwDeviceType, pInfo->dwDeviceType ); if (dwErr == 0) { dwErr = SetRegSz( hkeyDP, REGVAL_szNumber, pInfo->pszNumber ); } RegCloseKey( hkeyDP ); } else dwErr = ERROR_NOT_ENOUGH_MEMORY; if (dwErr != 0) break; } } RegCloseKey( hkeyCb ); return dwErr; } DWORD SetDefaultUserPreferences( OUT PBUSER* pUser, IN DWORD dwMode ) /* Fill caller's 'pUser' buffer with default user preferences. 'DwMode' ** indicates the type of user preferences. ** ** Returns 0 if successful, false otherwise. */ { DTLNODE* pNode; /* Set defaults. */ CopyMemory( pUser, &g_pbuserDefaults, sizeof(*pUser) ); pUser->pdtllistCallback = DtlCreateList( 0L ); pUser->pdtllistPhonebooks = DtlCreateList( 0L ); pUser->pdtllistAreaCodes = DtlCreateList( 0L ); pUser->pdtllistPrefixes = DtlCreateList( 0L ); pUser->pdtllistSuffixes = DtlCreateList( 0L ); pUser->pdtllistLocations = DtlCreateList( 0L ); if (!pUser->pdtllistCallback || !pUser->pdtllistPhonebooks || !pUser->pdtllistAreaCodes || !pUser->pdtllistPrefixes || !pUser->pdtllistSuffixes || !pUser->pdtllistLocations) { /* Can't even get empty lists, so we're forced to return an error. */ DestroyUserPreferences( pUser ); return ERROR_NOT_ENOUGH_MEMORY; } /* Add the default prefixes. */ pNode = CreatePszNode( TEXT("0,") ); if (pNode) DtlAddNodeLast( pUser->pdtllistPrefixes, pNode ); pNode = CreatePszNode( TEXT("9,") ); if (pNode) DtlAddNodeLast( pUser->pdtllistPrefixes, pNode ); pNode = CreatePszNode( TEXT("8,") ); if (pNode) DtlAddNodeLast( pUser->pdtllistPrefixes, pNode ); pNode = CreatePszNode( TEXT("70#") ); if (pNode) DtlAddNodeLast( pUser->pdtllistPrefixes, pNode ); if (dwMode == UPM_Logon) { ASSERT(pUser->dwPhonebookMode!=PBM_Personal); pUser->fShowLights = FALSE; pUser->fSkipConnectComplete = TRUE; } if (dwMode == UPM_Router) { pUser->dwCallbackMode = CBM_No; } pUser->fInitialized = TRUE; return 0; } DWORD SetLocationList( IN HKEY hkey, IN DTLLIST* pList ) /* Sets by-location tree under registry key 'hkey' to the list of ** by-location nodes 'pList'. ** ** Returns 0 if successful or an error code. */ { DWORD dwErr; TCHAR szId[ MAXLTOTLEN + 1 ]; DWORD cb; DWORD i; DWORD dwDisposition; HKEY hkeyL; HKEY hkeyId; DTLNODE* pNode; dwErr = RegCreateKeyEx( hkey, REGKEY_Location, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyL, &dwDisposition ); if (dwErr != 0) return dwErr; /* Delete all keys and values under the location key. */ for (;;) { cb = MAXLTOTLEN + 1; dwErr = RegEnumKeyEx( hkeyL, 0, szId, &cb, NULL, NULL, NULL, NULL ); if (dwErr != 0) break; dwErr = RegDeleteKey( hkeyL, szId ); if (dwErr != 0) break; } if (dwErr == ERROR_NO_MORE_ITEMS) dwErr = 0; if (dwErr == 0) { /* Add the new ID sub-trees. */ for (pNode = DtlGetFirstNode( pList ); pNode; pNode = DtlGetNextNode( pNode )) { LOCATIONINFO* pInfo; pInfo = (LOCATIONINFO* )DtlGetData( pNode ); ASSERT(pInfo); LToT( pInfo->dwLocationId, szId, 10 ); dwErr = RegCreateKeyEx( hkeyL, szId, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyId, &dwDisposition ); if (dwErr != 0) break; dwErr = SetRegDword( hkeyId, REGVAL_dwPrefix, pInfo->iPrefix ); if (dwErr == 0) dwErr = SetRegDword( hkeyId, REGVAL_dwSuffix, pInfo->iSuffix ); RegCloseKey( hkeyId ); if (dwErr != 0) break; } } RegCloseKey( hkeyL ); return dwErr; } DWORD WriteUserPreferences( IN HKEY hkey, IN PBUSER* pUser ) /* Write user preferences 'pUser' at RAS-Phonebook registry key 'hkey'. ** ** Returns 0 if successful or an error code. */ { DWORD dwErr; TRACE("WriteUserPreferences"); do { dwErr = SetRegDword( hkey, REGVAL_fOperatorDial, pUser->fOperatorDial ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_fPreviewPhoneNumber, pUser->fPreviewPhoneNumber ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_fUseLocation, pUser->fUseLocation ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_fShowLights, pUser->fShowLights ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_fShowConnectStatus, pUser->fShowConnectStatus ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_fNewEntryWizard, pUser->fNewEntryWizard ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_fCloseOnDial, pUser->fCloseOnDial ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_fAllowLogonPhonebookEdits, pUser->fAllowLogonPhonebookEdits ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_fAllowLogonLocationEdits, pUser->fAllowLogonLocationEdits ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_fSkipConnectComplete, pUser->fSkipConnectComplete ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_dwRedialAttempts, pUser->dwRedialAttempts ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_dwRedialSeconds, pUser->dwRedialSeconds ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_dwIdleDisconnectSeconds, pUser->dwIdleDisconnectSeconds ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_fRedialOnLinkFailure, pUser->fRedialOnLinkFailure ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_fPopupOnTopWhenRedialing, pUser->fPopupOnTopWhenRedialing ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_fExpandAutoDialQuery, pUser->fExpandAutoDialQuery ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_dwCallbackMode, pUser->dwCallbackMode ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_dwPhonebookMode, pUser->dwPhonebookMode ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_fUseAreaAndCountry, pUser->fUseAreaAndCountry ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_dwXWindow, pUser->dwXPhonebook ); if (dwErr != 0) break; dwErr = SetRegDword( hkey, REGVAL_dwYWindow, pUser->dwYPhonebook ); dwErr = SetCallbackList( hkey, pUser->pdtllistCallback ); if (dwErr != 0) break; dwErr = SetRegMultiSz( hkey, REGVAL_mszPhonebooks, pUser->pdtllistPhonebooks, NT_Psz ); if (dwErr != 0) break; dwErr = SetRegMultiSz( hkey, REGVAL_mszAreaCodes, pUser->pdtllistAreaCodes, NT_Psz ); if (dwErr != 0) break; dwErr = SetRegMultiSz( hkey, REGVAL_mszPrefixes, pUser->pdtllistPrefixes, NT_Psz ); if (dwErr != 0) break; dwErr = SetRegMultiSz( hkey, REGVAL_mszSuffixes, pUser->pdtllistSuffixes, NT_Psz ); if (dwErr != 0) break; dwErr = SetLocationList( hkey, pUser->pdtllistLocations ); if (dwErr != 0) break; dwErr = SetRegSz( hkey, REGVAL_szLastCallbackByCaller, pUser->pszLastCallbackByCaller ); if (dwErr != 0) break; dwErr = SetRegSz( hkey, REGVAL_szPersonalPhonebookFile, pUser->pszPersonalFile ); if (dwErr != 0) break; dwErr = SetRegSz( hkey, REGVAL_szAlternatePhonebookPath, pUser->pszAlternatePath ); if (dwErr != 0) break; dwErr = SetRegSz( hkey, REGVAL_szDefaultEntry, pUser->pszDefaultEntry ); if (dwErr != 0) break; RegDeleteValue( hkey, REGVAL_szPersonalPhonebookPath ); } while (FALSE); if (dwErr == 0) pUser->fDirty = FALSE; TRACE1("WriteUserPreferences=%d",dwErr); return dwErr; }