/* Copyright (c) 1992, Microsoft Corporation, all rights reserved ** ** util.c ** Remote Access External APIs ** Utility routines ** ** 10/12/92 Steve Cobb */ #include #include #include #include #include #include #include #include // Trace and assert #include #include #include #define EAP_CUSTOM_KEY 0x43424431 typedef struct _EAP_CUSTOM_DATA { DWORD dwSignature; DWORD dwCustomAuthKey; DWORD dwSize; BYTE abdata[1]; } EAP_CUSTOM_DATA; BOOL IsRouterPhonebook(LPCTSTR pszPhonebook) { const TCHAR *psz; BOOL fRouter = FALSE; if(NULL == pszPhonebook) { goto done; } psz = pszPhonebook + lstrlen(pszPhonebook); // // Seek back to the beginning of the filename // while(psz != pszPhonebook) { if(TEXT('\\') == *psz) { break; } psz--; } if(TEXT('\\') == *psz) { psz += 1; } TRACE1("IsRouterPhonebook: pbk=%ws", psz); //For whistler 524726 fRouter = ( CSTR_EQUAL == CompareString( LOCALE_INVARIANT, NORM_IGNORECASE, TEXT("router.pbk"), -1, psz, -1 ) ); done: return fRouter; } BOOL DwIsDefaultConnection( IN PWCHAR pszEntryName) { DWORD dwErr = NO_ERROR, dwCb = 0, dwCount = 1; RASAUTODIALENTRYW adEntry; INT iCmp; // Validate parameters // if (!pszEntryName) { return FALSE; } // Initialze // ZeroMemory(&adEntry, sizeof(adEntry)); dwCb = adEntry.dwSize = sizeof(adEntry); dwErr = RasGetAutodialAddressW( NULL, NULL, &adEntry, &dwCb, &dwCount); if (dwErr != NO_ERROR) { return FALSE; } iCmp = _wcsnicmp( adEntry.szEntry, pszEntryName, sizeof(adEntry.szEntry) / sizeof(WCHAR)); return (0 == iCmp); } DWORD DwPbentryToDetails( IN PBENTRY* pEntry, IN LPCWSTR pszPhonebookPath, IN BOOL fIsAllUsersPbk, OUT RASENUMENTRYDETAILS* pDetails) { DWORD dwErr = NO_ERROR; DTLNODE *pdtlnode; PBLINK *pLink; pDetails->dwSize = sizeof(RASENUMENTRYDETAILS); pDetails->dwType = pEntry->dwType; pDetails->fShowMonitorIconInTaskBar = pEntry->fShowMonitorIconInTaskBar; if(pEntry->pGuid) { pDetails->guidId = *pEntry->pGuid; } //For .Net 587396 lstrcpynW(pDetails->szEntryName, pEntry->pszEntryName, RASAPIP_MAX_ENTRY_NAME+1); pDetails->dwFlags = (fIsAllUsersPbk) ? REN_AllUsers : REN_User; if(pszPhonebookPath) { lstrcpynW(pDetails->szPhonebookPath, pszPhonebookPath, MAX_PATH + 1); } else { pDetails->szPhonebookPath[0] = L'\0'; } // // Get the devicename associated with the first // link in the list of entries associated with // this entry // pDetails->szDeviceName[0] = TEXT('\0'); pDetails->szPhoneNumber[0] = TEXT('\0'); pdtlnode = (DTLNODE *) DtlGetFirstNode(pEntry->pdtllistLinks); if(pdtlnode) { pLink = (PBLINK *) DtlGetData(pdtlnode); if( (NULL != pLink) && (pLink->pbport.pszDevice)) { pDetails->rdt = RdtFromPbdt( pLink->pbport.pbdevicetype, pLink->pbport.dwFlags); if(RAS_DEVICE_CLASS(pDetails->rdt) == RDT_Tunnel) { (void) DwGetVpnDeviceName( pEntry->dwVpnStrategy, pLink->pbport.pszDevice, pDetails->szDeviceName); } else { lstrcpy(pDetails->szDeviceName, pLink->pbport.pszDevice); } } // XP 351412 // // Populate the phone number as well // if( (NULL != pLink) && (pLink->pdtllistPhones)) { DTLNODE* pnodeNum = DtlGetFirstNode(pLink->pdtllistPhones); PBPHONE* pPhone = NULL; if (NULL != pnodeNum) { pPhone = DtlGetData(pnodeNum); if ((NULL != pPhone) && (NULL != pPhone->pszPhoneNumber)) { lstrcpyn( pDetails->szPhoneNumber, pPhone->pszPhoneNumber, RAS_MaxPhoneNumber); } } } } // Mark whether this is the default connection // XP 286752 // if (DwIsDefaultConnection(pEntry->pszEntryName)) { pDetails->dwFlagsPriv |= REED_F_Default; } return dwErr; } DWORD DwSendRasNotification( IN RASEVENTTYPE Type, IN PBENTRY* pEntry, IN LPCTSTR pszPhonebookPath, IN HANDLE hData) // Extra Type-specific info { RASEVENT RasEvent; DWORD dwErr = ERROR_SUCCESS; ZeroMemory((PBYTE) &RasEvent, sizeof(RASEVENT)); RasEvent.Type = Type; // // Ignore the notification if this is a router interface // if(IsRouterPhonebook(pszPhonebookPath)) { goto done; } switch(Type) { case ENTRY_ADDED: case ENTRY_MODIFIED: case ENTRY_AUTODIAL: { BOOL fAllUsers = TRUE; if (NULL != pszPhonebookPath) { fAllUsers = IsPublicPhonebook(pszPhonebookPath); } DwPbentryToDetails( pEntry, pszPhonebookPath, fAllUsers, &(RasEvent.Details) ); break; } case ENTRY_DELETED: case ENTRY_RENAMED: { if(NULL != pEntry->pGuid) { RasEvent.guidId = *pEntry->pGuid; } if(ENTRY_RENAMED == Type) { lstrcpy(RasEvent.pszwNewName, pEntry->pszEntryName); } break; } default: { #if DBG ASSERT(FALSE); #endif goto done; } } dwErr = RasSendNotification(&RasEvent); done: return dwErr; } DWORD DwGetCustomAuthData(PBENTRY *pEntry, DWORD *pcbCustomAuthData, PBYTE *ppCustomAuthData) { DWORD retcode = SUCCESS; DWORD cbOffset = 0; EAP_CUSTOM_DATA *pCustomData = NULL; ASSERT(NULL != pcbCustomAuthData); ASSERT(NULL != ppCustomAuthData); ASSERT(NULL != pEntry); *pcbCustomAuthData = 0; *ppCustomAuthData = NULL; // // first check to see if we understand the format of the // eap blob stored in the phonebook // if(NULL == pEntry->pCustomAuthData) { goto done; } if( (sizeof(DWORD) > pEntry->cbCustomAuthData) || ((*((DWORD *) pEntry->pCustomAuthData)) != EAP_CUSTOM_KEY)) { Free(pEntry->pCustomAuthData); pEntry->pCustomAuthData = NULL; pEntry->cbCustomAuthData = 0; goto done; } // // Loop through the blob and return the blob corresponding // to the eap type of the entry // while(cbOffset < pEntry->cbCustomAuthData) { pCustomData = (EAP_CUSTOM_DATA *) ((PBYTE) pEntry->pCustomAuthData + cbOffset); if( (sizeof(DWORD) > (pEntry->cbCustomAuthData - cbOffset)) || ((*((DWORD *) pEntry->pCustomAuthData)) != EAP_CUSTOM_KEY)) { // // The data is corrupt. Blow away the data. // should we return an error? // Free(pEntry->pCustomAuthData); pEntry->pCustomAuthData = NULL; pEntry->cbCustomAuthData = 0; TRACE("GetCustomAuthdata: data is corrupt"); goto done; } if(pCustomData->dwCustomAuthKey == pEntry->dwCustomAuthKey) { break; } cbOffset += sizeof(EAP_CUSTOM_DATA) + pCustomData->dwSize; } if(cbOffset < pEntry->cbCustomAuthData) { *pcbCustomAuthData = pCustomData->dwSize; *ppCustomAuthData = pCustomData->abdata; } done: return retcode; } DWORD DwSetCustomAuthData(PBENTRY *pEntry, DWORD cbCustomAuthData, PBYTE pCustomAuthData) { DWORD retcode = SUCCESS; DWORD cbOffset = 0; EAP_CUSTOM_DATA *pCustomData = NULL; DWORD dwSize; PBYTE pNewCustomAuthData; ASSERT(NULL != pEntry); if(NULL != pEntry->pCustomAuthData) { if( (sizeof(DWORD) > pEntry->cbCustomAuthData) || ((*((DWORD *) pEntry->pCustomAuthData)) != EAP_CUSTOM_KEY)) { Free(pEntry->pCustomAuthData); pEntry->pCustomAuthData = NULL; pEntry->cbCustomAuthData = 0; } } // // Find the old Eap Data // while(cbOffset < pEntry->cbCustomAuthData) { pCustomData = (EAP_CUSTOM_DATA *) ((PBYTE)pEntry->pCustomAuthData + cbOffset); if( (sizeof(DWORD) > (pEntry->cbCustomAuthData - cbOffset)) || ((*((DWORD *) pEntry->pCustomAuthData)) != EAP_CUSTOM_KEY)) { // // The data is corrupt. Blow away the data. // should we return an error? // Free(pEntry->pCustomAuthData); pEntry->pCustomAuthData = NULL; pEntry->cbCustomAuthData = 0; TRACE("SetCustomAuthData: data is corrupt!"); break; } if(pCustomData->dwCustomAuthKey == pEntry->dwCustomAuthKey) { break; } cbOffset += (sizeof(EAP_CUSTOM_DATA) + pCustomData->dwSize); } // // Prefast warning // if( (NULL != pCustomData) && (cbOffset < pEntry->cbCustomAuthData)) { dwSize = sizeof(EAP_CUSTOM_DATA) + pCustomData->dwSize; ASSERT(pEntry->cbCustomAuthData >= (cbOffset + dwSize)); MoveMemory(pEntry->pCustomAuthData + cbOffset, pEntry->pCustomAuthData + cbOffset + dwSize, pEntry->cbCustomAuthData - cbOffset - dwSize); pEntry->cbCustomAuthData -= dwSize; } if(0 == pEntry->cbCustomAuthData) { Free0(pEntry->pCustomAuthData); pEntry->pCustomAuthData = NULL; } if( (0 == cbCustomAuthData) || (NULL == pCustomAuthData)) { goto done; } dwSize = cbCustomAuthData + pEntry->cbCustomAuthData + sizeof(EAP_CUSTOM_DATA); pNewCustomAuthData = Malloc(dwSize); if(NULL == pNewCustomAuthData) { retcode = E_OUTOFMEMORY; goto done; } ZeroMemory(pNewCustomAuthData, dwSize); CopyMemory(pNewCustomAuthData, pEntry->pCustomAuthData, pEntry->cbCustomAuthData); pCustomData = (EAP_CUSTOM_DATA *) (pNewCustomAuthData + pEntry->cbCustomAuthData); pCustomData->dwSignature = EAP_CUSTOM_KEY; pCustomData->dwCustomAuthKey = pEntry->dwCustomAuthKey; pCustomData->dwSize = cbCustomAuthData; CopyMemory(pCustomData->abdata, pCustomAuthData, cbCustomAuthData); pEntry->cbCustomAuthData = dwSize; if(NULL != pEntry->pCustomAuthData) { Free(pEntry->pCustomAuthData); } pEntry->pCustomAuthData = pNewCustomAuthData; done: return retcode; } DWORD DwGetVpnDeviceName( DWORD dwVpnStrategy, WCHAR *pszDeviceDefault, WCHAR *pszDeviceName) { DWORD dwErr = ERROR_SUCCESS, dwType; CHAR szDeviceName[MAX_DEVICE_NAME]; // Figure out the device name we're interested in // discovering. // dwType = RDT_Tunnel_L2tp; switch (dwVpnStrategy) { case VS_Default: case VS_L2tpFirst: case VS_L2tpOnly: dwType = RDT_Tunnel_L2tp; break; case VS_PptpFirst: case VS_PptpOnly: dwType = RDT_Tunnel_Pptp; break; } TRACE1("RasGetDeviceName(rdt=%d)...", dwType); dwErr = RasGetDeviceNameW( dwType, pszDeviceName); TRACE1("RasGetDeviceName. 0x%x", dwErr); if(ERROR_SUCCESS != dwErr) { dwErr = ERROR_SUCCESS; // We can't determine from rasman -- use the phonebook // value if possible // if (NULL != pszDeviceDefault) { lstrcpyn( pszDeviceName, pszDeviceDefault, RASAPIP_MAX_DEVICE_NAME); } } return dwErr; } BOOL IsServerOS ( ) { BOOL fServerOS = TRUE; //Default //Check to see if the OS is server - Data Center, Server, Advanced Server OSVERSIONINFOEX stOsvEx; ZeroMemory( &stOsvEx, sizeof(stOsvEx) ); stOsvEx.dwOSVersionInfoSize = sizeof(stOsvEx); GetVersionEx((LPOSVERSIONINFO)&stOsvEx); if ( stOsvEx.wProductType == VER_NT_WORKSTATION ) fServerOS = FALSE; return fServerOS; }