//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1998. // // File: D U N I M P O R T . C P P // // Contents: Functions that handles .DUN files for RAS connections // created in win9x // // Notes: // // Author: TongL 15 March 1999 // //---------------------------------------------------------------------------- #include "pch.h" #pragma hdrstop #include "dunimport.h" #include "raserror.h" #include "ncras.h" #include "connutil.h" #define RAS_MaxEntryName 256 #define MAXLONGLEN 11 // Maximum long string length #define MAXIPADDRLEN 20 #define SIZE_ReadBuf 0x00008000 // 32K buffer size #define NUM_IP_FIELDS 4 #define MIN_IP_VALUE 0 #define MAX_IP_VALUE 255 #define CH_DOT L'.' const WCHAR c_szPhoneBookPath[] = L"\\Microsoft\\Network\\Connections\\Pbk\\rasphone.pbk"; const WCHAR c_szRASDT[] = L"RASDT_"; const WCHAR c_szEntrySection[] = L"Entry"; const WCHAR c_szEntryName[] = L"Entry_Name"; const WCHAR c_szML[] = L"Multilink"; const WCHAR c_szPhoneSection[] = L"Phone"; const WCHAR c_szDialAsIs[] = L"Dial_As_Is"; const WCHAR c_szPhoneNumber[] = L"Phone_Number"; const WCHAR c_szAreaCode[] = L"Area_Code"; const WCHAR c_szCountryCode[] = L"Country_Code"; const WCHAR c_szCountryID[] = L"Country_ID"; const WCHAR c_szYes[] = L"yes"; const WCHAR c_szNo[] = L"no"; const WCHAR c_szDeviceSection[] = L"Device"; const WCHAR c_szDeviceType[] = L"Type"; const WCHAR c_szModem[] = L"modem"; const WCHAR c_szVpn[] = L"vpn"; const WCHAR c_szDeviceName[] = L"Name"; const WCHAR c_szServerSection[] = L"Server"; const WCHAR c_szServerType[] = L"Type"; const WCHAR c_szPPP[] = L"PPP"; const WCHAR c_szSLIP[] = L"SLIP"; const WCHAR c_szRAS[] = L"RAS"; const WCHAR c_szSWCompress[] = L"SW_Compress"; const WCHAR c_szPWEncrypt[] = L"PW_Encrypt"; const WCHAR c_szNetLogon[] = L"Network_Logon"; const WCHAR c_szSWEncrypt[] = L"SW_Encrypt"; const WCHAR c_szNetBEUI[] = L"Negotiate_NetBEUI"; const WCHAR c_szIPX[] = L"Negotiate_IPX/SPX"; const WCHAR c_szIP[] = L"Negotiate_TCP/IP"; const WCHAR c_szIPSection[] = L"TCP/IP"; const WCHAR c_szIPSpec[] = L"Specify_IP_Address"; const WCHAR c_szIPAddress[] = L"IP_address"; const WCHAR c_szServerSpec[] = L"Specify_Server_Address"; const WCHAR c_szDNSAddress[] = L"DNS_address"; const WCHAR c_szDNSAltAddress[] = L"DNS_Alt_address"; const WCHAR c_szWINSAddress[] = L"WINS_address"; const WCHAR c_szWINSAltAddress[]= L"WINS_Alt_address"; const WCHAR c_szIPCompress[] = L"IP_Header_Compress"; const WCHAR c_szRemoteGateway[] = L"Gateway_On_Remote"; //+--------------------------------------------------------------------------- // // Function: HrInvokeDunFile_Internal // // Purpose: This is the entry point for DUN file invoking // // Arguments: // szFileName [in] The .DUN file name // // Returns: S_OK if succeeded, failure code otherwise // HRESULT HrInvokeDunFile_Internal(IN LPWSTR szDunFile) { HRESULT hr = S_OK; WCHAR szEntryName[RAS_MaxEntryName+1]; tstring strPhoneBook; hr = HrGetPhoneBookFile(strPhoneBook); if (SUCCEEDED(hr)) { // Get the size of device configuration // This also validates an exported file // hr = HrGetEntryName(szDunFile, szEntryName, strPhoneBook); if ((HRESULT_FROM_WIN32(ERROR_CANNOT_OPEN_PHONEBOOK) == hr) || (HRESULT_FROM_WIN32(ERROR_CANNOT_FIND_PHONEBOOK_ENTRY) == hr)) { // create a new entry in the current user's phonebook hr = HrImportPhoneBookInfo(szDunFile, szEntryName, strPhoneBook); } if (SUCCEEDED(hr)) { // get the GUID of this connection RASENTRY* pRasEntry = NULL; hr = HrRasGetEntryProperties( strPhoneBook.c_str(), szEntryName, &pRasEntry, NULL); if(SUCCEEDED(hr)) { // dial the connection hr = HrLaunchConnection(pRasEntry->guidId); MemFree(pRasEntry); } } } TraceError("HrInvokeDunFile_Internal", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: HrGetPhoneBookFile // // Purpose: This function will return the proper path to the current user's // phonebook. // // Arguments: // szFileName [in] The .DUN file name // // Returns: S_OK if succeeded, failure code otherwise // HRESULT HrGetPhoneBookFile(tstring& strPhoneBook) { HRESULT hr = S_OK; strPhoneBook = c_szEmpty; LPITEMIDLIST pidl; LPMALLOC pMalloc; WCHAR szDir[MAX_PATH+1]; hr = SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidl); if(SUCCEEDED(hr)) { if (SHGetPathFromIDList(pidl, szDir)) { strPhoneBook = szDir; TraceTag(ttidDun, "The path to the application directory is: %S", strPhoneBook.c_str()); // release the memory by using the the shell's IMalloc ptr // if (SUCCEEDED(SHGetMalloc(&pMalloc))) { pMalloc->Free(pidl); } } else { hr = E_FAIL; } } if (SUCCEEDED(hr)) { TraceTag(ttidDun, "The path to the phonebook is: %S", strPhoneBook.c_str()); strPhoneBook += c_szPhoneBookPath; } return hr; } //+--------------------------------------------------------------------------- // // Function: HrGetEntryName // // Purpose: This function validates and returns the entry name // // Arguments: // szDunFile [in] The .dun file created on win9x // szEntryName [in] The entry name for this connection // // Returns: S_OK if valid and is a new entry // S_FALSE if valid and but is an existing entry // otherwise, specific error // HRESULT HrGetEntryName(IN LPWSTR szFileName, IN LPWSTR szEntryName, tstring & strPhoneBook) { HRESULT hr = S_OK; DWORD dwRet; // Get the entry name // dwRet = GetPrivateProfileString(c_szEntrySection, c_szEntryName, c_szEmpty, szEntryName, RAS_MaxEntryName+1, szFileName); // no entry name if (dwRet <= 0) { return HRESULT_FROM_WIN32(ERROR_CORRUPT_PHONEBOOK); } // Check if entry name already exists in phonebook // RASENTRY* pRasEntry = NULL; hr = HrRasGetEntryProperties( strPhoneBook.c_str(), szEntryName, &pRasEntry, NULL); MemFree(pRasEntry); TraceErrorOptional("HrGetEntryName", hr, ((HRESULT_FROM_WIN32(ERROR_CANNOT_OPEN_PHONEBOOK) == hr) || (HRESULT_FROM_WIN32(ERROR_CANNOT_FIND_PHONEBOOK_ENTRY) == hr))); return hr; } //+--------------------------------------------------------------------------- // // Function: HrImportPhoneBookInfo // // Purpose: This function checks if the RAS entry already exists in the // current user's phonebook // // Arguments: // szEntryName [in] The entry name for this connection // // Returns: TRUE if already exists, FALSE otherwise // HRESULT HrImportPhoneBookInfo( IN LPWSTR szDunFile, IN LPWSTR szEntryName, tstring & strPhoneBook) { HRESULT hr = S_OK; RASENTRY RasEntry = {0}; // Get the phone number // hr = HrImportPhoneInfo(&RasEntry, szDunFile); if (SUCCEEDED(hr)) { // Get device name, type and config // ImportDeviceInfo(&RasEntry, szDunFile); // Get Server Type settings // ImportServerInfo(&RasEntry, szDunFile); // Get IP address // ImportIPInfo(&RasEntry, szDunFile); // Prompt for user name and password RasEntry.dwfOptions |= RASEO_PreviewUserPw; // Save it to the phonebook // DWORD dwRet; RasEntry.dwSize = sizeof(RASENTRY); RasEntry.dwType = RASET_Phone; dwRet = RasSetEntryProperties(strPhoneBook.c_str(), szEntryName, &RasEntry, sizeof(RASENTRY), NULL, 0); hr = HRESULT_FROM_WIN32(dwRet); TraceError("RasSetEntryProperties", hr); } TraceError("HrImportPhoneBookInfo", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: HrImportPhoneInfo // // Purpose: This function imports the phone number // // Arguments: // szFileName [in] The .DUN file name // // Returns: // HRESULT HrImportPhoneInfo(RASENTRY * pRasEntry, IN LPWSTR szFileName) { HRESULT hr = S_OK; // szLocalPhoneNumber if (GetPrivateProfileString(c_szPhoneSection, c_szPhoneNumber, c_szEmpty, pRasEntry->szLocalPhoneNumber, celems(pRasEntry->szLocalPhoneNumber), szFileName) == 0) { hr = HRESULT_FROM_WIN32(ERROR_CORRUPT_PHONEBOOK); }; if (SUCCEEDED(hr)) { WCHAR szYesNo[MAXLONGLEN+1]; GetPrivateProfileString(c_szPhoneSection, c_szDialAsIs, c_szYes, szYesNo, celems(szYesNo), szFileName); // Do we have to get country code and area code? // if (!lstrcmpiW(szYesNo, c_szNo)) { // use country and area codes pRasEntry->dwfOptions |= RASEO_UseCountryAndAreaCodes; // If we cannot get the country ID or it is zero, default to dial as is // if ((pRasEntry->dwCountryID = GetPrivateProfileInt( c_szPhoneSection, c_szCountryID, 0, szFileName)) != 0) { pRasEntry->dwCountryCode = GetPrivateProfileInt(c_szPhoneSection, c_szCountryCode, 1, szFileName); } GetPrivateProfileString(c_szPhoneSection, c_szAreaCode, c_szEmpty, pRasEntry->szAreaCode, celems(pRasEntry->szAreaCode), szFileName); }; } TraceError("HrImportPhoneInfo", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: ImportDeviceInfo // // Purpose: This function imports the device info // // Arguments: // szFileName [in] The .DUN file name // // Returns: // VOID ImportDeviceInfo(RASENTRY * pRasEntry, IN LPWSTR szFileName) { WCHAR szDeviceType[RAS_MaxDeviceType+1]; // Get the device type // if (GetPrivateProfileString(c_szDeviceSection, c_szDeviceType, c_szEmpty, szDeviceType, celems(szDeviceType), szFileName)) { if (!lstrcmpiW(szDeviceType, c_szModem)) { lstrcpyW(pRasEntry->szDeviceType, RASDT_Modem); } else if (!lstrcmpiW(szDeviceType, c_szVpn)) { lstrcpyW(pRasEntry->szDeviceType, RASDT_Vpn); } else { AssertSz(FALSE, "Unknown device type"); } // Get the device name // GetPrivateProfileString( c_szDeviceSection, c_szDeviceName, c_szEmpty, pRasEntry->szDeviceName, celems(pRasEntry->szDeviceName), szFileName); } } //+--------------------------------------------------------------------------- // // Function: ImportServerInfo // // Purpose: This function imports the server type name and settings // // Arguments: // szFileName [in] The .DUN file name // // Returns: // VOID ImportServerInfo(RASENTRY * pRasEntry, IN LPWSTR szFileName) { HRESULT hr = S_OK; WCHAR szValue[MAXLONGLEN]; WCHAR szYesNo[MAXLONGLEN]; DWORD dwRet; // Get the server type: PPP, SLIP or RAS // if (GetPrivateProfileString(c_szServerSection, c_szServerType, c_szEmpty, szValue, celems(szValue), szFileName)) { if (!lstrcmpiW(szValue, c_szPPP)) { pRasEntry->dwFramingProtocol = RASFP_Ppp; } else if (!lstrcmpiW(szValue, c_szSLIP)) { pRasEntry->dwFramingProtocol = RASFP_Slip; } else if (!lstrcmpiW(szValue, c_szRAS)) { pRasEntry->dwFramingProtocol = RASFP_Ras; } } // SW_Compress // if (GetPrivateProfileString(c_szServerSection, c_szSWCompress, c_szEmpty, szYesNo, celems(szYesNo), szFileName)) { if (!lstrcmpiW(szYesNo, c_szYes)) { pRasEntry->dwfOptions |= RASEO_SwCompression; }; }; // PW_Encrypt // if (GetPrivateProfileString(c_szServerSection, c_szPWEncrypt, c_szEmpty, szYesNo, celems(szYesNo), szFileName)) { if (!lstrcmpiW(szYesNo, c_szYes)) { pRasEntry->dwfOptions |= RASEO_RequireEncryptedPw; }; }; // Network_Logon // if (GetPrivateProfileString(c_szServerSection, c_szNetLogon, c_szEmpty, szYesNo, celems(szYesNo), szFileName)) { if (!lstrcmpiW(szYesNo, c_szYes)) { pRasEntry->dwfOptions |= RASEO_NetworkLogon; }; }; // SW_Encrypt // // set both RASEO_RequireMsEncryptedPw and RASEO_RequireDataEncryption // if SW_Encrypt is TRUE // if (GetPrivateProfileString(c_szServerSection, c_szSWEncrypt, c_szEmpty, szYesNo, celems(szYesNo), szFileName)) { if (!lstrcmpiW(szYesNo, c_szYes)) { pRasEntry->dwfOptions |= RASEO_RequireMsEncryptedPw; pRasEntry->dwfOptions |= RASEO_RequireDataEncryption; }; }; // Get the network protocols to negotiate // if (GetPrivateProfileString(c_szServerSection, c_szNetBEUI, c_szEmpty, szYesNo, celems(szYesNo), szFileName)) { if (!lstrcmpiW(szYesNo, c_szYes)) { pRasEntry->dwfNetProtocols |= RASNP_NetBEUI; }; }; if (GetPrivateProfileString(c_szServerSection, c_szIPX, c_szEmpty, szYesNo, celems(szYesNo), szFileName)) { if (!lstrcmpiW(szYesNo, c_szYes)) { pRasEntry->dwfNetProtocols |= RASNP_Ipx; }; }; if (GetPrivateProfileString(c_szServerSection, c_szIP, c_szEmpty, szYesNo, celems(szYesNo), szFileName)) { if (!lstrcmpiW(szYesNo, c_szYes)) { pRasEntry->dwfNetProtocols |= RASNP_Ip; }; }; } //+--------------------------------------------------------------------------- // // Function: ImportIPInfo // // Purpose: This function imports the device info // // Arguments: // szFileName [in] The .DUN file name // // Returns: // VOID ImportIPInfo(RASENTRY * pRasEntry, IN LPWSTR szFileName) { WCHAR szIPAddr[MAXIPADDRLEN]; WCHAR szYesNo[MAXLONGLEN]; // Import IP address information // if (GetPrivateProfileString(c_szIPSection, c_szIPSpec, c_szEmpty, szYesNo, celems(szYesNo), szFileName)) { if (!lstrcmpiW(szYesNo, c_szYes)) { pRasEntry->dwfOptions |= RASEO_SpecificIpAddr; // Get the IP address // if (GetPrivateProfileString(c_szIPSection, c_szIPAddress, c_szEmpty, szIPAddr, celems(szIPAddr), szFileName)) { SzToRasIpAddr(szIPAddr, &(pRasEntry->ipaddr)); }; } }; // Import Server address information // if (GetPrivateProfileString(c_szIPSection, c_szServerSpec, c_szEmpty, szYesNo, celems(szYesNo), szFileName)) { if (!lstrcmpiW(szYesNo, c_szYes)) { // The import file has server address specified, get the server address // pRasEntry->dwfOptions |= RASEO_SpecificNameServers; if (GetPrivateProfileString(c_szIPSection, c_szDNSAddress, c_szEmpty, szIPAddr, celems(szIPAddr), szFileName)) { SzToRasIpAddr(szIPAddr, &(pRasEntry->ipaddrDns)); }; if (GetPrivateProfileString(c_szIPSection, c_szDNSAltAddress, c_szEmpty, szIPAddr, celems(szIPAddr), szFileName)) { SzToRasIpAddr(szIPAddr, &(pRasEntry->ipaddrDnsAlt)); }; if (GetPrivateProfileString(c_szIPSection, c_szWINSAddress, c_szEmpty, szIPAddr, celems(szIPAddr), szFileName)) { SzToRasIpAddr(szIPAddr, &(pRasEntry->ipaddrWins)); }; if (GetPrivateProfileString(c_szIPSection, c_szWINSAltAddress, c_szEmpty, szIPAddr, celems(szIPAddr), szFileName)) { SzToRasIpAddr(szIPAddr, &(pRasEntry->ipaddrWinsAlt)); }; } }; // Header compression and the gateway settings // if (GetPrivateProfileString(c_szIPSection, c_szIPCompress, c_szEmpty, szYesNo, celems(szYesNo), szFileName)) { if (!lstrcmpiW(szYesNo, c_szYes)) { pRasEntry->dwfOptions |= RASEO_IpHeaderCompression; } }; if (GetPrivateProfileString(c_szIPSection, c_szRemoteGateway, c_szEmpty, szYesNo, celems(szYesNo), szFileName)) { if (!lstrcmpiW(szYesNo, c_szYes)) { pRasEntry->dwfOptions |= RASEO_RemoteDefaultGateway; } }; } VOID SzToRasIpAddr(IN LPWSTR szIPAddress, OUT RASIPADDR * pIpAddr) { list listFields; ConvertStringToColString(szIPAddress, CH_DOT, listFields); list::const_iterator iter = listFields.begin(); if (listFields.size() == NUM_IP_FIELDS) { // Go through each field and get the number value BYTE a = _wtol((*iter++)->c_str()); BYTE b = _wtol((*iter++)->c_str()); BYTE c = _wtol((*iter++)->c_str()); BYTE d = _wtol((*iter++)->c_str()); // validate the address if ((a >= MIN_IP_VALUE) && (a <= MAX_IP_VALUE) && (b >= MIN_IP_VALUE) && (b <= MAX_IP_VALUE) && (c >= MIN_IP_VALUE) && (c <= MAX_IP_VALUE) && (d >= MIN_IP_VALUE) && (d <= MAX_IP_VALUE)) { pIpAddr->a = a; pIpAddr->b = b; pIpAddr->c = c; pIpAddr->d = d; } } FreeCollectionAndItem(listFields); }