Ejemplo n.º 1
0
int RsaCreateLink(LPCTSTR szEntry, HWND hDlgWnd)
{
	ghRasConn = NULL;
	LPRASENTRY lpRasEntry = NULL;
	DWORD dwBufferSize = 0;
	DWORD dwRet = 0;
	DWORD rgep_res;
	DWORD dwDevInfo = 0;
	rgep_res = RasGetEntryProperties(NULL, L"", NULL, &dwBufferSize, NULL, &dwDevInfo);
	if (dwBufferSize == 0)
		return -1;
	lpRasEntry = (LPRASENTRY)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufferSize);
	if (lpRasEntry == NULL)
		return -2;
	ZeroMemory(lpRasEntry, sizeof(RASENTRY));
	lpRasEntry->dwSize = dwBufferSize;
	lpRasEntry->dwfOptions = RASEO_RemoteDefaultGateway;
	lpRasEntry->dwType = RASET_Broadband;

	lstrcpy(lpRasEntry->szDeviceType, RASDT_PPPoE);
	lstrcpy(lpRasEntry->szDeviceName, NULL);
	lpRasEntry->dwfNetProtocols = RASNP_Ip;
	lpRasEntry->dwFramingProtocol = RASFP_Ppp;

	dwRet = RasSetEntryProperties(NULL, szEntry, lpRasEntry, dwBufferSize, NULL, dwDevInfo); // 创建连接
	HeapFree(GetProcessHeap(), 0, (LPVOID)lpRasEntry);
	if (dwRet == ERROR_CANNOT_OPEN_PROFILE)
	{
		MessageBox(hDlgWnd,
			L"电话簿已经被破坏或丢失成分",
			L"错误",
			MB_OK);
	}
	return 0;
}
Ejemplo n.º 2
0
 VOID CreateRASEntry(HINSTANCE hinst) 
 {
     DWORD           cb;
     RASENTRY        RasEntry;
 
     TCHAR name[256];
     LoadString(hinst, IDS_DEFAULT_NAME, name, 256);
 
     // This will create the default entries if the key does not exist. 
     RasEntry.dwSize = sizeof(RASENTRY);
     cb = sizeof(RASENTRY);
     RasGetEntryProperties (NULL, TEXT(""), &RasEntry, &cb, NULL, NULL);
 
     // Now set up the entry the way we want it (like "`115200 Default")
     LoadString(hinst, SOCKET_FRIENDLY_NAME, RasEntry.szDeviceName, RAS_MaxDeviceName + 1);
 
     // And finally, write the new entry out
     if ( RasSetEntryProperties (NULL, name,
                                 &RasEntry, sizeof(RasEntry), NULL, 0) ) 
     {
         DEBUGMSG (1, (TEXT("Error %d from RasSetEntryProperties\r\n"),
                       GetLastError()));
     } 
     else 
     {
         HKEY hKey;
         DWORD dwDisp;
         DEBUGMSG (1, (TEXT("RasEntry '%s' Created\r\n"), name));
         if (ERROR_SUCCESS==RegCreateKeyEx(HKEY_CURRENT_USER, RK_CONTROLPANEL_COMM, 0, NULL, REG_OPTION_NON_VOLATILE,
                KEY_ALL_ACCESS, NULL, &hKey, &dwDisp))
         {
            RegSetValueEx(hKey, RV_CNCT, 0, REG_SZ, (LPBYTE)name, sizeof(TCHAR)*(1+lstrlen(name)));
            RegCloseKey(hKey);
         }
     }
 
     // Now, delete the link file.
     DeleteLink(hinst);
}
Ejemplo n.º 3
0
BOOL setEntryProperties() {
    DWORD error = ERROR_SUCCESS;
    // Find buffer size
    DWORD dwBufferSize = 0;
    RasGetEntryProperties(NULL, L"", NULL, &dwBufferSize, NULL, NULL);

    if (dwBufferSize == 0) {
        fwprintf(stderr, L"[setEntryProperties] error=%d\n", error);
        return FALSE;
    }

    LPRASENTRY entry = NULL;
    entry = (LPRASENTRY)HeapAlloc(GetProcessHeap(),
                                  HEAP_ZERO_MEMORY,
                                  dwBufferSize);

    entry->dwType = RASET_Broadband;
    entry->dwfNetProtocols = RASNP_Ip;
    entry->dwFramingProtocol = RASFP_Ppp;
    entry->dwSize = dwBufferSize;
    entry->dwfOptions |= RASEO_RemoteDefaultGateway;
    lstrcpy(entry->szDeviceType, RASDT_PPPoE);
    lstrcpy(entry->szLocalPhoneNumber, ENTRY_NAME_W);

    error = RasSetEntryProperties(PHONE_BOOK,
                                  ENTRY_NAME_W,
                                  entry,
                                  dwBufferSize,
                                  NULL,
                                  0);
    if (error) {
        fwprintf(stderr, L"[setEntryProperties] error=%d\n", error);
    }
    HeapFree(GetProcessHeap(), 0, entry);
    return !error;
}
Ejemplo n.º 4
0
//
// RasCustomEntryDlg
//
// this export is the custom dial entry when RasEntryDlg has been called by
// an application - the call is forwarded to here and it is up to this
// function then to display, handle and update the phonebook entry that is
// being modified through its own dialog or other means
//
extern "C" BOOL WINAPI  RasCustomEntryDlg (
  HINSTANCE hInstDll,       // handle to DLL instance
  LPTSTR lpszPhonebook,     // pointer to the full path and 
                            //  file name of the phone-book file
  LPTSTR lpszEntry,         // pointer to the name of the
                            //  phone-book entry to edit,
                            //  copy, or create
  LPRASENTRYDLG lpInfo      // pointer to a structure that
                            //  contains additional parameters
)
{
    DWORD rc = 0;           // return code
    DWORD dwSize = 0;       // size of buffer
    //RASENTRY RasEntry;      // Ras Entry structure
    PSAMPLE_CUSTOM_ENTRY_DATA pEntryData = NULL;    // pointer to allocated strucutre for passing data
    LPRASENTRY pLocalRE = NULL;
    LPRASENTRY pMemberRE = NULL;

    OutputTraceString(L"RasCustomEntryDlg called in customdial.dll\n");

    // Check input parameters
    if (!lpszEntry || !lpInfo)
    {
        return FALSE;
    }

    // create buffer of data to move back and forth between dialog
    dwSize = sizeof(SAMPLE_CUSTOM_ENTRY_DATA);

    pEntryData = (PSAMPLE_CUSTOM_ENTRY_DATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
    if (pEntryData)
    {
        CopyMemory(&(pEntryData->tEntryDlg), lpInfo, sizeof(RASENTRYDLG));

        dwSize = sizeof(RASENTRY);

        pLocalRE = (LPRASENTRY)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
        if (NULL == pLocalRE)
        {
            return FALSE;
        }

        // get the other parameters for the entry (phone and Device Name)
        
        pLocalRE->dwSize = dwSize;
        
        rc = RasGetEntryProperties(lpszPhonebook, lpszEntry, pLocalRE, &dwSize, NULL, NULL);
        if (ERROR_BUFFER_TOO_SMALL == rc)
        {
            if (HeapFree(GetProcessHeap(), 0, (LPVOID)pLocalRE))
            {
                pLocalRE = (LPRASENTRY)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);

                if (NULL == pLocalRE)
                {
                    return FALSE;
                }
            }
            else
            {
                return FALSE;
            }

            // get the other parameters for the entry (phone and Device Name)
            
            pLocalRE->dwSize = dwSize;
            rc = RasGetEntryProperties(lpszPhonebook, lpszEntry, pLocalRE, &dwSize, NULL, NULL);
        }


        pMemberRE = (LPRASENTRY)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
        if (NULL == pMemberRE)
        {
            HeapFree(GetProcessHeap(), 0, (LPVOID)pMemberRE);
            return FALSE;
        }

        // Set size and save pointer into structure
        pMemberRE->dwSize = dwSize;
        pEntryData->ptEntry = pMemberRE;
        pMemberRE = NULL;

        if (ERROR_SUCCESS == rc)
        {
            CopyMemory(pEntryData->ptEntry, pLocalRE , pEntryData->ptEntry->dwSize);
        }
        else
        {
            MessageBox(NULL, L"Copy Memory failed", L"Error", MB_OK);
        }    
        
        StringCchCopy(pEntryData->szEntryName, CELEMS(pEntryData->szEntryName), lpszEntry);
        StringCchCopy(pEntryData->szPhoneBookPath, CELEMS(pEntryData->szPhoneBookPath), lpszPhonebook);

        OutputTraceString(L"--- Call Custom Entry Dialog\n");      
        
        INT_PTR ret = DialogBoxParam(hInstDll, MAKEINTRESOURCE(IDD_CUSTOMENTRYDLG), lpInfo->hwndOwner, CustomEntryDlgProc, (LPARAM) pEntryData);

        OutputTraceString(L"--- Return from Custom Entry Dialog: %d\n", rc);      

        if (ret > 0)   // dialog succeeded
        {      
            // copy entry name into lpInfo structure for return
            StringCchCopy(lpInfo->szEntry, CELEMS(lpInfo->szEntry), (LPTSTR) pEntryData->szEntryName);

            // check to see if anything has changed and change the entry
            LPRASENTRY lpRasEntry = pEntryData->ptEntry;

            if ((lstrcmpi(pLocalRE->szLocalPhoneNumber, lpRasEntry->szLocalPhoneNumber) != 0) ||
                (lstrcmpi(pLocalRE->szDeviceName, lpRasEntry->szDeviceName) != 0) ||
                (lstrcmpi(lpInfo->szEntry, lpszEntry) != 0))
            {        
                OutputTraceString(L"--- Calling RasSetEntryProperties to make changes\n");
                if (rc = RasSetEntryProperties(lpszPhonebook, lpInfo->szEntry, lpRasEntry, lpRasEntry->dwSize, NULL, 0) != SUCCESS)
                {
                    OutputTraceString(L"--- RasSetEntryProperties() failed: %d\n", rc);
                    lpInfo->dwError = rc;
                    rc = FALSE;
                }
                else 
                {
                    OutputTraceString(L"--- RasSetEntryProperties() succeeded.\n", rc);
                    rc = TRUE;
                }
            }
            else
            {
                rc = TRUE;      
            }
        }
        else
        {
            lpInfo->dwError = GetLastError();
            OutputTraceString(L"DialogBox Failed (or cancelled) in RasCustomEntryDlg (GetLastError = %d)\n", lpInfo->dwError);
            rc = FALSE;
        }

        if (pLocalRE)
        {
            HeapFree(GetProcessHeap(), 0, (LPVOID)pLocalRE);
            pLocalRE = NULL;
        }

        if (pEntryData->ptEntry)
        {
            HeapFree(GetProcessHeap(), 0, (LPVOID)pEntryData->ptEntry);
            pEntryData->ptEntry = NULL;
        }

        HeapFree(GetProcessHeap(), 0, (LPVOID)pEntryData);
        pEntryData = NULL;

    }
    else
    {
        OutputTraceString(L"--- Memory allocation failed (HeapAlloc) in RasCustomEntryDlg (GetLastError = %d)\n", GetLastError());
    }
 
    OutputTraceString(L"RasCustomEntryDlg exiting customdial.dll with return code: %d\n", rc);

    return rc;
}
Ejemplo n.º 5
0
void CreateConnection()
{
	const size_t NeedRebootMsgChars = 64;
	bool doDisableIPSec = false;
	LPWSTR connTitle = NULL;
	int typeConnection = (int)SendMessage(hWndComboBox, CB_GETCURSEL, 0, 0);

	WORD  cLoginLength                 = 0;
	TCHAR lpszLoginText[maxChars+1]    = {0};
	WORD  cPasswordLength              = 0;
	TCHAR lpszPasswordText[maxChars+1] = {0};
	// Получение текста логина и пароля
	cLoginLength    = (WORD)SendMessage(hWndLogin,    EM_LINELENGTH, 0, 0);
	cPasswordLength = (WORD)SendMessage(hWndPassword, EM_LINELENGTH, 0, 0);
	if (cLoginLength > maxChars) {
		MessageBox(hwnd, TEXT("Значение поля \"Пользователь\" не должно превышать 20-ти символов."), TEXT("Ошибка"), MB_OK);
		return;
	}
	if (cPasswordLength > maxChars) {
		MessageBox(hwnd, TEXT("Значение поля \"Пароль\" не должно превышать 20-ти символов."), TEXT("Ошибка"), MB_OK);
		return;
	}
	*((LPWORD)lpszLoginText)    = cLoginLength;
	*((LPWORD)lpszPasswordText) = cPasswordLength;
	SendMessage(hWndLogin,    EM_GETLINE, 0, (LPARAM)lpszLoginText);
	SendMessage(hWndPassword, EM_GETLINE, 0, (LPARAM)lpszPasswordText);
	// Корректное окончание строк (null-terminated)
	lpszLoginText[cLoginLength]       = 0;
	lpszPasswordText[cPasswordLength] = 0;

	// Первичная проверка версии ОС
	if (os_ver.dwPlatformId != VER_PLATFORM_WIN32_NT) {
		MessageBox(hwnd, TEXT("Устаревшая или нераспознанная версия операционной системы"), TEXT("Ошибка"), MB_OK);
		CloseApplication();
	}

	// Произвести отключение IPSec при успешном создании L2TP соединения
	if (ver == 51) { // Windows XP?
		if (typeConnection == 0) { // L2TP?
			if (isAdmin) { // Администратор?
				doDisableIPSec = true;
			}
			else {
				MessageBox(hwnd, TEXT("Для создания L2TP соединения в Windows XP\nнеобходимо запустить программу с правами администратора."), TEXT("Уведомление"), MB_OK);
				return;
			}
		}
	}

	// Получение размера структуры, независящее от версии ОС.
	int rasentry_struct_size = sizeof(RASENTRY);
	/* кусок старого кода, может, пригодится?
	if ((os_ver.dwMajorVersion == 5 && os_ver.dwMinorVersion == 0) || os_ver.dwMajorVersion <= 4) {
		// указание для старых ОС размера структуры RASENTRY
		rasentry_struct_size = 2088;
	}
	*/
	DWORD dwDeviceInfoSize = 0;
	DWORD dwRasEntryRet = RasGetEntryProperties(NULL, NULL, NULL, (LPDWORD)&rasentry_struct_size, NULL, &dwDeviceInfoSize);
	if (dwRasEntryRet == ERROR_RASMAN_CANNOT_INITIALIZE) {
		MessageBox(hwnd, TEXT("Не запущена служба \"Диспетчер подключений удалённого доступа\" (RasMan)\nЗапустите службу и повторите операцию."), TEXT("Уведомление"), MB_OK);
		return;
	}

	// Заполнение структуры настроек соединения
	RASENTRY rasEntry;
	ZeroMemory(&rasEntry, sizeof(RASENTRY));
	rasEntry.dwSize = rasentry_struct_size;
	rasEntry.dwfOptions = RASEO_RemoteDefaultGateway | RASEO_ModemLights |
			RASEO_SecureLocalFiles | RASEO_RequireMsEncryptedPw | RASEO_RequireDataEncryption |
			RASEO_RequireMsCHAP2 | RASEO_ShowDialingProgress;
	if (BST_CHECKED == SendMessage(hWndRequestLogin, BM_GETSTATE, 0, 0)) {
		rasEntry.dwfOptions = rasEntry.dwfOptions | RASEO_PreviewUserPw;
	}
	rasEntry.dwfOptions2 = RASEO2_DisableNbtOverIP | RASEO2_ReconnectIfDropped | RASEO2_Internet |
			RASEO2_DontNegotiateMultilink | RASEO2_SecureClientForMSNet | RASEO2_SecureFileAndPrint;
	rasEntry.dwRedialCount = 3;
	rasEntry.dwRedialPause = 60;
	rasEntry.dwFramingProtocol = RASFP_Ppp;
	rasEntry.dwfNetProtocols = RASNP_Ip;
	rasEntry.dwEncryptionType = ET_Optional; // ET_Require
	switch (typeConnection) {
	case 1: //PPPoE
		connTitle = connTitlePPPoE;
		wcscpy_s(rasEntry.szLocalPhoneNumber, 9, TEXT("in-doors"));
		wcscpy_s(rasEntry.szDeviceType, 6, RASDT_PPPoE);
		rasEntry.dwVpnStrategy = VS_Default;
		rasEntry.dwType = RASET_Broadband;
		break;
	case 2: // PPTP
		connTitle = connTitlePPTP;
		wcscpy_s(rasEntry.szLocalPhoneNumber, 21, TEXT("internet.in-doors.ru"));
		wcscpy_s(rasEntry.szDeviceType, 4, RASDT_Vpn);
		rasEntry.dwVpnStrategy = VS_PptpOnly;
		rasEntry.dwType = RASET_Vpn;
		break;
	case 0: // L2TP
	default:
		connTitle = connTitleL2TP;
		wcscpy_s(rasEntry.szLocalPhoneNumber, 17, TEXT("l2tp.in-doors.ru"));
		wcscpy_s(rasEntry.szDeviceType, 4, RASDT_Vpn);
		rasEntry.dwVpnStrategy = VS_L2tpOnly;
		rasEntry.dwType = RASET_Vpn;
		break;
	}
	//rasEntry.dwDialMode = RASEDM_DialAll;
	//wcscpy_s(rasEntry.szDeviceName, 21, TEXT("VPN"));

	//RASDIALPARAMS ras_param;
	RASCREDENTIALS ras_cred;

	// Непосредственно - создание соединения.
	dwRasEntryRet = RasSetEntryProperties(NULL, connTitle, &rasEntry, rasentry_struct_size, NULL, 0);
	switch (dwRasEntryRet) {
	case ERROR_ACCESS_DENIED:
		MessageBox(hwnd, TEXT("Не удалось создать подключение\nRasSetEntryProperties() - ERROR_ACCESS_DENIED"), TEXT("Ошибка"), MB_OK);
		break;
	case ERROR_BUFFER_INVALID:
		MessageBox(hwnd, TEXT("Не удалось создать подключение\nRasSetEntryProperties() - ERROR_BUFFER_INVALID"), TEXT("Ошибка"), MB_OK);
		break;
	case ERROR_CANNOT_OPEN_PHONEBOOK:
		MessageBox(hwnd, TEXT("Не удалось создать подключение\nRasSetEntryProperties() - ERROR_CANNOT_OPEN_PHONEBOOK"), TEXT("Ошибка"), MB_OK);
		break;
	case ERROR_INVALID_PARAMETER:
		MessageBox(hwnd, TEXT("Не удалось создать подключение\nRasSetEntryProperties() - ERROR_INVALID_PARAMETER"), TEXT("Ошибка"), MB_OK);
		break;
	case ERROR_SUCCESS:
		// Указание логина и пароля соединения. Необязательное действие, если используется RasSetCredentials().
		/*
		ZeroMemory(&ras_param, sizeof(RASDIALPARAMS));
		ras_param.dwSize = sizeof(RASDIALPARAMS);
		wcscpy_s(ras_param.szEntryName, wcslen(connTitle)+1, connTitle);
		wcscpy_s(ras_param.szUserName, 256, lpszLoginText);
		wcscpy_s(ras_param.szPassword, 256, lpszPasswordText);
		DWORD dwRasEntryParamsRet = RasSetEntryDialParams(0, &ras_param, FALSE);
		switch (dwRasEntryParamsRet) {
		case ERROR_BUFFER_INVALID:
			MessageBox(hwnd, TEXT("Не удалось задать логин и пароль\nRasSetEntryDialParams() - ERROR_BUFFER_INVALID"), TEXT("Ошибка"), MB_OK);
			break;
		case ERROR_CANNOT_OPEN_PHONEBOOK:
			MessageBox(hwnd, TEXT("Не удалось задать логин и пароль\nRasSetEntryDialParams() - ERROR_CANNOT_OPEN_PHONEBOOK"), TEXT("Ошибка"), MB_OK);
			break;
		case ERROR_CANNOT_FIND_PHONEBOOK_ENTRY:
			MessageBox(hwnd, TEXT("Не удалось задать логин и пароль\nRasSetEntryDialParams() - ERROR_CANNOT_FIND_PHONEBOOK_ENTRY"), TEXT("Ошибка"), MB_OK);
			break;
		case ERROR_SUCCESS:
		default:
			break;
		}
		*/

		// Управление логином и паролем соединения.
		ZeroMemory(&ras_cred, sizeof(RASCREDENTIALS));
		ras_cred.dwSize = sizeof(RASCREDENTIALS);
		ras_cred.dwMask = RASCM_UserName | RASCM_Password; // | RASCM_DefaultCreds;
		if (BST_CHECKED == SendMessage(hWndSaveCredentials, BM_GETSTATE, 0, 0)) {
			// сохранить логин и пароль
			wcscpy_s(ras_cred.szUserName, 256, lpszLoginText);
			wcscpy_s(ras_cred.szPassword, 256, lpszPasswordText);
			DWORD dwRasCredRet = RasSetCredentials(NULL, connTitle, &ras_cred, FALSE);
			switch (dwRasCredRet) {
			case ERROR_CANNOT_OPEN_PHONEBOOK:
				MessageBox(hwnd, TEXT("Не удалось сохранить логин и пароль\nRasSetCredentials() - ERROR_CANNOT_OPEN_PHONEBOOK"), TEXT("Ошибка"), MB_OK);
				break;
			case ERROR_CANNOT_FIND_PHONEBOOK_ENTRY:
				MessageBox(hwnd, TEXT("Не удалось сохранить логин и пароль\nRasSetCredentials() - ERROR_CANNOT_FIND_PHONEBOOK_ENTRY"), TEXT("Ошибка"), MB_OK);
				break;
			case ERROR_INVALID_PARAMETER:
				MessageBox(hwnd, TEXT("Не удалось сохранить логин и пароль\nRasSetCredentials() - ERROR_INVALID_PARAMETER"), TEXT("Ошибка"), MB_OK);
				break;
			case ERROR_INVALID_SIZE:
				MessageBox(hwnd, TEXT("Не удалось сохранить логин и пароль\nRasSetCredentials() - ERROR_INVALID_SIZE"), TEXT("Ошибка"), MB_OK);
				break;
			case ERROR_ACCESS_DENIED:
				MessageBox(hwnd, TEXT("Не удалось сохранить логин и пароль\nRasSetCredentials() - ERROR_ACCESS_DENIED"), TEXT("Ошибка"), MB_OK);
				break;
			case ERROR_SUCCESS:
			default:
				break;
			}
		}
		else {
			// очистить логин и пароль
			RasSetCredentials(NULL, connTitle, &ras_cred, TRUE);
		}

		TCHAR strNeedRebootStr[NeedRebootMsgChars];
		ZeroMemory(strNeedRebootStr, NeedRebootMsgChars * sizeof(TCHAR));

		if (doDisableIPSec) {
			FixIPSec();
			StringCbPrintf(strNeedRebootStr, NeedRebootMsgChars * sizeof(TCHAR), TEXT("\nТребуется перезагрузка компьютера."));
		}

		if (BST_CHECKED == SendMessage(hWndCreateLnk, BM_GETSTATE, 0, 0)) {
			CreateLnkOnDesktop(connTitle);
		}

		TCHAR lptstrSuccessMsg[256];
		StringCbPrintf(lptstrSuccessMsg, 256 * sizeof(TCHAR), TEXT("VPN соединение \"%s\" создано.%s"), connTitle, strNeedRebootStr);
		MessageBox(hwnd, lptstrSuccessMsg, TEXT("Уведомление"), MB_OK);
		break;
	default:
		int const arraysize = 254;
		TCHAR lptstrStatupOSPaert[arraysize];
		StringCbPrintf(lptstrStatupOSPaert, arraysize * sizeof(TCHAR), TEXT("Не удалось создать подключение\nRasSetEntryProperties() - Код ошибки: %d"), dwRasEntryRet);
		MessageBox(hwnd, lptstrStatupOSPaert, TEXT("Ошибка"), MB_OK);
		break;
	}
}
Ejemplo n.º 6
0
/*
 *  XXX - currently fails badly (without useful error) if VPN profile already
 *  exists and is active (connected).
 */
int rashelper_configure_profile(char *profile_name,
                                char *desktop_shortcut_name,
                                char *server_address,
                                char *preshared_key,
                                char *username,
                                int ppp_compression_enabled,
                                int default_route_enabled,
                                int create_desktop_shortcut,
                                int open_profile_after_creation)
{
        RASCREDENTIALS Credentials = {0};
        RASDIALDLG RasDlg = {0};
        RASENTRY RasEntry = {0};
        RASENTRY RasEntry2 = {0};
        DWORD dwErr = NO_ERROR;
        DWORD dwSize;
        int retval = RASHELPER_FAILED;

        printf("rashelper_configure_profile: starting\n");

        // validate entry, if one exists or entry is invalid this fails
        dwErr = rashelper_validate_phonebook_entry(profile_name);
        
        if (dwErr != NO_ERROR)
                return dwErr;

        printf("rashelper_configure_profile: phonebook validation step OK\n");

        // Define RASENTRY for RAS Phonebook
        // http://msdn2.microsoft.com/en-us/library/aa377274.aspx
        RasEntry.dwSize                 = sizeof(RASENTRY);
        RasEntry.dwType                 = RASET_Vpn;
        RasEntry.dwVpnStrategy          = VS_L2tpOnly;
        RasEntry.dwEncryptionType       = ET_Require;
        RasEntry.dwfNetProtocols        = RASNP_Ip;
        // XXX: other options like RASEO_IpHeaderCompression (may be set by default), RASEO_RequireEncryptedPw (?)
        RasEntry.dwfOptions             = RASEO_RequireMsEncryptedPw | RASEO_RequireDataEncryption | RASEO_PreviewUserPw | RASEO_ShowDialingProgress | RASEO_ModemLights;
#ifndef AUTOCONFIGURE_WIN2000
	/* XP and upwards */
	RasEntry.dwfOptions2            = RASEO2_UsePreSharedKey | RASEO2_ReconnectIfDropped | RASEO2_DontNegotiateMultilink;
	RasEntry.dwRedialCount          = 50;
	RasEntry.dwRedialPause          = 10;
#endif
        RasEntry.dwSubEntries           = 0;
        RasEntry.dwDialMode             = 0;
        strcpy(RasEntry.szDeviceType, RASDT_Vpn);
        strcpy(RasEntry.szLocalPhoneNumber, server_address);

        /*
         *  XXX: This doesn't work in Windows XP.  The failure is related to the following
         *  registry key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters,
         *  value DontAddDefaultGatewayDefault (normally set to 0).  This value needs to be 1 for
         *  this setting to have an effect, but we'd have to modify and restore the value.
         *
         *  Because we always want default route enabled, there's no point in fixing this bug
         *  now.
         */

        if (default_route_enabled)
        {
                RasEntry.dwfOptions |= RASEO_RemoteDefaultGateway;
        }

        if (ppp_compression_enabled)
        {
                RasEntry.dwfOptions |= RASEO_SwCompression;
        }

        printf("rashelper_configure_profile: creating ras entry to phonebook\n");

        // Create RAS Entry to phonebook
        // http://msdn2.microsoft.com/en-us/library/aa377827.aspx
        dwErr = RasSetEntryProperties(NULL, profile_name, &RasEntry, sizeof(RASENTRY), NULL, 0);
        if (dwErr != NO_ERROR) {
                retval = RASHELPER_FAILED;
                goto cleanup;
        }
        printf("RasSetEntryProperties() successful\n");

        /*
         *  Read properties back, we want the actual device name
         */
        RasEntry2.dwSize = sizeof(RASENTRY);
        dwSize = sizeof(RASENTRY);
        dwErr = RasGetEntryProperties(NULL, profile_name, &RasEntry2, &dwSize, NULL, 0);
        if (dwErr != NO_ERROR) {
                retval = RASHELPER_FAILED;
                goto cleanup;
        }
        printf("deviceName: %s\n", RasEntry2.szDeviceName);
        
        // Set pre-shared key
        // http://msdn2.microsoft.com/en-us/library/aa377811.aspx
        Credentials.dwSize = sizeof(RASCREDENTIALS);
        Credentials.dwMask = RASCM_PreSharedKey;
        strcpy(Credentials.szPassword, preshared_key);  // FIXME: check copy size

        dwErr = RasSetCredentials(NULL, profile_name, &Credentials, FALSE);

        if (dwErr != NO_ERROR) {
                retval = RASHELPER_FAILED;
                goto cleanup;
        }

        if (username != NULL)
        {
                memset(&Credentials, 0, sizeof(RASCREDENTIALS));

                Credentials.dwSize = sizeof(RASCREDENTIALS);
                Credentials.dwMask = RASCM_UserName;
                strcpy(Credentials.szUserName, username);

                dwErr = RasSetCredentials(NULL, profile_name, &Credentials, FALSE);

                if (dwErr != NO_ERROR) {
                        retval = RASHELPER_FAILED;
                        goto cleanup;
                }
        }

        if (create_desktop_shortcut)
        {
                int rc;

                rc = create_shell_link_to_network_connection(CSIDL_DESKTOP,
                                                             desktop_shortcut_name, 
                                                             profile_name);
                if (rc != 0) {
                        // FIXME: ignore error, this is best effort now?
                        ;
                }
        }

        /*
         *  Vista "set network type" fix is not possible at this, commented out
         *  because this does not work.
         */
#if 0
        /* FIXME: this is too early, the Network List Manager has not "seen" the connection yet */
        if (1) {
                int rc;

                rc = set_vista_network_type(profile_name);
                printf("__set_vista_network_type() returned %d\n", rc);
        }
#endif

        if (open_profile_after_creation)
        {
            HWND wnd = NULL;

                /* http://msdn2.microsoft.com/en-us/library/aa377023(VS.85).aspx */
                /* just in case */
                memset(&RasDlg, 0x00, sizeof(RASDIALDLG));

                /*
                 *  Find foreground window in an attempt to avoid opening the RAS
                 *  dialog to "background" in Windows Vista SP0.
                 */
        
                /* http://msdn2.microsoft.com/en-us/library/ms633505(VS.85).aspx */
                wnd = GetForegroundWindow();
                if (wnd == NULL) {
                        /* OK, not really fatal */
                        printf("rashelper_configure_profile(): cannot open temporary window\n");
                        ;
                }

                /*
                 *  Call RasDialDlg().  See:
                 *
                 *    http://msdn2.microsoft.com/en-us/library/aa377020.aspx
                 *
                 *  RasDlg.hwndOwner could be NULL (no window to which the dialog
                 *  is attached), but without an underlying "on the top" window, the
                 *  dialog can go to the background.  So we try to use the foreground
                 *  window (but fail gracefully if it is not available).  This fix
                 *  seems to be only required in Windows Vista (not in Windows XP SP2).
                 */

                RasDlg.dwSize = sizeof(RASDIALDLG);
                RasDlg.hwndOwner = wnd;
                if (!RasDialDlg(NULL, profile_name, NULL, &RasDlg))
                {
                        /*
                         *  RasDlg.dwError == 0 => user cancel.  However, basically all
                         *  errors here should be ignored: we've already got the profile
                         *  configured, so an error saying "cannot configure profile"
                         *  would be incorrect.
                         */
#if 0                           
                        if (RasDlg.dwError != 0) {
                                /* Zero is apparently user cancel */
                                SetLastError(RasDlg.dwError);
                                retval = RASHELPER_FAILED;
                                goto cleanup;
                        }
#endif
                }
        }

                /*
                 *  FIXME: this is a temporary hack test.  We're racing Vista to set the
                 *  network category (after dialup connection is complete; whose success
                 *  we don't currently check for).  Ultimately we'd need to implement the
                 *  INetworkEvents API and get callbacks for new networks and run the
                 *  whole thing from there.
                 *
                 *  Most disappointing of all, even this racy version doesn't work, so
                 *  this part is disabled entirely :-(
                 */
#if 0
                for (int i = 0; i < 50; i++) {
                        Sleep(200);

                        if (1) {
                                int rc;
                                
                                rc = set_vista_network_type(profile_name);
                                printf("set_vista_network_type() returned %d\n", rc);
                        }
                }
#endif

        retval = RASHELPER_OK;
        /* fall through */

 cleanup:
        return retval;
}