Hi
I must create programmatically a new connection to a VPN network whit "Cellular Line (GPRS)".What's wrong in this code?
#include "stdafx.h"
#include <commctrl.h>
#include <aygshell.h>
#include <sipapi.h>
// (DEBUT) DECLARATIONS+PROTOTYPES CONCERNANT LES ENTREES RAS
// Code ajouté pour entrées RAS
#include "stdlib.h"
#include "tchar.h"
#include "windows.h"
// ----
#include "ras.h"
#include "raserror.h"
#include "tapi.h"
#ifndef TAPI_CURRENT_VERSION
#define TAPI_CURRENT_VERSION 0x00020000
#endif
#define TAPI_VERSION_1_0 0x00010003
#define TAPI_VERSION_3_0 0x00030000
LPVARSTRING lpDevCfg = NULL;
DWORD WINAPI GetDevCfg(DWORD dwLineId, HWND Hwnd, bool bShowDialog);
DWORD WINAPI RasEnumDev(LPWSTR lpstr);
DWORD WINAPI RasEnum(LPWSTR lpstr);
DWORD WINAPI test();
DWORD WINAPI CreateRasEntry(LPWSTR lpszName, LPWSTR lpszLogin, LPWSTR lpszPassword, LPWSTR lpszDeviceName);
DWORD GetConnectionStatus();
BOOLEAN showErr=TRUE; BOOLEAN debug=TRUE;
DWORD TraitementsRAS(); // SPECIFIQUE A CETTE APPLICATION
// (FIN) DECLARATIONS+PROTOTYPES CONCERNANT LES ENTREES RAS
// (DEBUT) DECLARATIONS+PROTOTYPES CONCERNANT LA BASE DE REGISTRES
#include "winreg.h"
DWORD WriteKey();
DWORD DeleteKey();
// (FIN) DECLARATIONS+PROTOTYPES CONCERNANT LA BASE DE REGISTRES
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // The current instance
HWND hwndCB; // The command bar handle
static SHACTIVATEINFO s_sai;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
//RasEnum(_T(""));
// RasEnumDev(_T(""));
TraitementsRAS();
// test();
return TRUE;
}
DWORD WINAPI test(){
//RETAILMSG(1,(TEXT("start\r\n")));
RASENTRY RasEntry;
RASDIALPARAMS RasDialParams;
HRASCONN hRasConn=NULL;
DWORD dwSize;
DWORD dwError;
TCHAR szError[100];
TCHAR szMsg[100];
// Initialize the RASENTRY structure.
dwSize=sizeof(RasEntry);
memset (&RasEntry, 0, dwSize);
RasEntry.dwSize=dwSize;
RasEntry.dwfOptions=0;
wcscpy(RasEntry.szLocalPhoneNumber,TEXT("4"));
RasEntry.dwfNetProtocols=RASNP_Ip;
RasEntry.dwFramingProtocol=RASFP_Ppp;
wcscpy(RasEntry.szDeviceType,RASDT_Modem);
// Get the name of the modem, i left this function out...
//InitializeTAPI();
wcscpy(RasEntry.szDeviceName,_T("Cellular Line"));
// Create a new phone-book entry.
dwError=RasSetEntryProperties(NULL,
TEXT("entry"),&RasEntry,sizeof(RASENTRY),NULL,0);
if (dwError!=0)
{
wsprintf (szError, TEXT("Unable to create the phonebook entry!%ld\r\n"),dwError);
MessageBox(NULL, szError, _T("ERROR:GetDevCfg"), MB_OK);
//RETAILMSG(1,(szError));
return(0);
}
// Initialize the RASDIALPARAMS structure.
memset (&RasDialParams,0,sizeof(RasDialParams));
RasDialParams.dwSize=sizeof(RasDialParams);
wcscpy(RasDialParams.szEntryName,TEXT("entry"));
RasDialParams.szPhoneNumber[0]=NULL;
RasDialParams.szCallbackNumber[0]=NULL;
wcscpy(RasDialParams.szUserName,TEXT("testuser"));
wcscpy(RasDialParams.szPassword,TEXT("secret"));
wcscpy(RasDialParams.szDomain,TEXT("testdomain"));
// Change the connection data.
dwError=RasSetEntryDialParams (NULL, &RasDialParams, FALSE);
if (dwError!=0)
{
wsprintf (szError, TEXT("Unable to set the connection information.")
TEXT(" Error %ld\r\n"), dwError);
MessageBox(NULL, szError, _T("ERROR:GetDevCfg"), MB_OK);
//RETAILMSG(1,(szError));
return(0);
}
hRasConn = NULL;
DWORD dwRval;
dwRval=RasDial(NULL,NULL,&RasDialParams,0,NULL,&hRasConn);
if (dwRval!=0)
{
wsprintf(szMsg,TEXT("Error RasDial(): %ld\r\n"),dwRval);
MessageBox(NULL,szMsg, _T("ERROR:GetDevCfg"), MB_OK);
}
else
{
MessageBox(NULL,_T("RasDial ok!"), _T("ERROR:GetDevCfg"), MB_OK);
}
return(0);
}
DWORD WINAPI TraitementsRAS() {
DWORD ret;
TCHAR szMess[128];
wsprintf(szMess, _T("OK per lanciare la connessione Cancel per annullarla"));
int rep=MessageBox(NULL, szMess, _T("Connessione"), MB_OKCANCEL);
if (rep!=IDCANCEL) {
// OBTENTION DEVICE CONFIGURATION POUR dwLineID=1 (Modem IrDA générique) HKEY_LOC_MACH\DRIVERS\BUILTIN
ret=GetDevCfg(3,NULL,FALSE);
if ( (ret!=0) && (showErr==TRUE) ) {
wsprintf(szMess, _T("ret=%ld"), ret);
MessageBox(NULL, szMess, _T("ERROR:GetDevCfg"), MB_OK);
}
else {
if (debug==TRUE) {
wsprintf(szMess, _T("ret=%ld"), ret);
MessageBox(NULL, szMess, _T("DBG:GetDevCfg:OK"), MB_OK);
}
}
// RAS CREATE ENTRY
ret=CreateRasEntry(_T("RFI"),_T("pippo"),_T("pippo"), _T("Cellular Line (GPRS)"));
if ( (ret!=0) && (showErr==TRUE) ) {
wsprintf(szMess, _T("ret=%ld"), ret);
MessageBox(NULL, szMess, _T("ERROR:CreateRasEntry"), MB_OK);
}
else {
if (debug==TRUE) {
wsprintf(szMess, _T("ret=%ld"), ret);
MessageBox(NULL, szMess, _T("DBG:CreateRasEntry:OK"), MB_OK);
}
}
// PER RENDERE VISIBILE LA CONNESSIONE
WriteKey();
// RAS DIAL ENTRY
RASDIALPARAMS rasDialParam;
// Configure the RASDIALPARAMS structure.
rasDialParam.dwSize = sizeof (RASDIALPARAMS);
rasDialParam.szPhoneNumber[0] = TEXT('\0');
rasDialParam.szCallbackNumber[0] = TEXT('\0');
wcscpy (rasDialParam.szEntryName, _T("RFI"));
HRASCONN rasConn=NULL;
unsigned long connection;
ret=RasDial(NULL, NULL, &rasDialParam, NULL, NULL, &rasConn);
if ( (ret!=0) && (showErr==TRUE) ) {
wsprintf(szMess, _T("ret=%ld"), ret);
MessageBox(NULL, szMess, _T("ERROR:RasDial"), MB_OK);
}
else {
if (debug==TRUE) {
wsprintf(szMess, _T("ret=%ld"), ret);
MessageBox(NULL, szMess, _T("DBG:RasDial:OK"), MB_OK);
}
}
if (ret==0) {
connection = (unsigned long) rasConn;
wsprintf(szMess, _T("Cliquez sur OK lorsque vous voudrez déconnecter la borne infrarouge..."));
MessageBox(NULL, szMess, _T("JAHLIGHT CONNEXION INFRAROUGE"), MB_OK);
}
/*
ret=RasHangUp((HRASCONN) connection);
if ( (ret!=0) && (showErr==TRUE) ) {
wsprintf(szMess, _T("ret=%ld"), ret);
MessageBox(NULL, szMess, _T("ERROR:RasHangUp"), MB_OK);
}
else {
if (debug==TRUE) {
wsprintf(szMess, _T("ret=%ld"), ret);
MessageBox(NULL, szMess, _T("DBG:RasHangUp:OK"), MB_OK);
}
}
DeleteKey();
LPWSTR lpszEntry=_T("JAHLIGHT");
ret=RasDeleteEntry(NULL, lpszEntry);
if ( (ret!=0) && (showErr==TRUE) ) {
wsprintf(szMess, _T("RasDeleteEntry returned %ld"), ret);
MessageBox(NULL, szMess, _T("ERROR:RasDeleteEntry"), MB_OK);
}
else {
if (debug==TRUE) {
wsprintf(szMess, _T("ret=%ld"), ret);
MessageBox(NULL, szMess, _T("DBG:RasDeleteEntry:OK"), MB_OK);
}
}
*/
}
return 0;
}
DWORD WINAPI GetDevCfg(DWORD dwLineId, HWND Hwnd, bool bShowDialog)
{
DWORD dwErr = 0;
LPVARSTRING cfg = NULL;
WCHAR lpszString[20];
wcscpy(lpszString,_T("/0"));
if (!(cfg = (LPVARSTRING) LocalAlloc(LPTR, 280)))
{
return 1;
}
if (!(lpDevCfg = (LPVARSTRING) LocalAlloc(LPTR, 280)))
{
return 1;
}
cfg->dwTotalSize = 280;
cfg->dwStringFormat=STRINGFORMAT_BINARY;
lpDevCfg->dwTotalSize = 280;
lpDevCfg->dwStringFormat=STRINGFORMAT_BINARY;
if (bShowDialog)
{
dwErr = lineGetDevConfig(dwLineId, cfg, _T("tapi/line"));
dwErr = lineConfigDialogEdit(dwLineId, Hwnd , _T("tapi/line"),
(LPVOID)((LPBYTE)cfg + cfg->dwStringOffset),
cfg->dwNeededSize,
lpDevCfg);
}
else
{
dwErr = lineGetDevConfig(dwLineId, lpDevCfg, _T("tapi/line"));
}
return dwErr;
LocalFree(cfg);
}
void WINAPI RasHang(HRASCONN &connection)
{
if (connection == 0)
connection = NULL;
if (connection != NULL)
{
RasHangUp(connection);
connection = NULL;
}
else
MessageBox(NULL,_T("Pas de connexion active."),_T("Connexions"),MB_OK | MB_ICONWARNING);
}
DWORD WINAPI RasConnect(LPWSTR sName, DWORD &connection)
{
HRASCONN g_hRasConn = NULL;
RASDIALPARAMS rasDialParams;
DWORD dwRes;
BOOL bPassword;
rasDialParams.dwSize = sizeof(RASDIALPARAMS);
wcscpy(rasDialParams.szEntryName,sName);
dwRes = RasGetEntryDialParams(NULL, &rasDialParams, &bPassword);
if (dwRes != 0)
{
// Error getting Dial params
return dwRes;
}
if(!bPassword)
MessageBox(NULL,_T("Pas de mot de passe"),_T("Connexions"),MB_OK | MB_ICONINFORMATION);
dwRes = RasDial(NULL,NULL,&rasDialParams,0,NULL,&g_hRasConn);
if (dwRes != 0)
{
// Error Dialing RAS
RasHangUp(g_hRasConn);
g_hRasConn = NULL;
return dwRes;
}
connection = (unsigned long)g_hRasConn;
return dwRes;
}
DWORD WINAPI RasEnum(LPWSTR lpstr) {
LPRASENTRYNAME lpRasEntry = NULL;
RASENTRY RasEntry;
DWORD dwRes,dwError, dwSize, dwSize2, dwEntries, dw;
TCHAR szError[100];
WCHAR szTmp[255];
wcscpy(szTmp,_T(""));
lpRasEntry = new RASENTRYNAME[20];
if(lpRasEntry == NULL) {
return 1;
}
lpRasEntry[0].dwSize = sizeof(RASENTRYNAME);
dwSize = sizeof(RASENTRYNAME) * 20;
memset(&RasEntry,0,sizeof(RASENTRY));
dwSize2 = sizeof(RASENTRY);
RasEntry.dwSize = dwSize2;
dwRes = RasEnumEntries(NULL, NULL, lpRasEntry, &dwSize, &dwEntries);
if (dwRes != 0)
MessageBox(NULL,_T("Error getting RAS entries"),_T("Connexions"),MB_OK | MB_ICONWARNING);
else {
//for(dw = 0; dw < dwEntries; dw++) {
for(dw = 0; dw < 1; dw++) {
MessageBox(NULL,lpRasEntry[dw].szEntryName,_T("TEST"),MB_OK);
// Retrieve the entry properties
if (dwError = RasGetEntryProperties(NULL, lpRasEntry[dw].szEntryName, &RasEntry, &dwSize2, NULL, NULL)) {
wsprintf(szError, _T("Unable to read default entry properties.")_T(" Error %ld"),dwError);
MessageBox(NULL,szError,_T("RasGetEntryProperties Error"),MB_OK | MB_ICONWARNING);
}
else{
// RASIPADDR mio = RasEntry.ipaddr;
wsprintf(szError, _T("dwfOptions")_T(" Error %ld"),RasEntry.dwCountryCode);
MessageBox(NULL,szError,_T("TROVO"),MB_OK | MB_ICONWARNING);
// MessageBox(NULL,mio.a,_T("ipaddr"),MB_OK | MB_ICONWARNING);
//RASIPADDR
/*
wsprintf(szError, _T("dwFramingProtocol")_T(" Error %ld"),RasEntry.dwFramingProtocol);
MessageBox(NULL,szError,_T("TROVO"),MB_OK | MB_ICONWARNING);
wsprintf(szError, _T("dwAlternatesOffset")_T(" Error %ld"),RasEntry.dwAlternatesOffset);
MessageBox(NULL,szError,_T("TROVO"),MB_OK | MB_ICONWARNING);
wsprintf(szError, _T("dwFrameSize")_T(" Error %ld"),RasEntry.dwFrameSize);
MessageBox(NULL,szError,_T("TROVO"),MB_OK | MB_ICONWARNING);
wsprintf(szError, _T("dwfNetProtocols")_T(" Error %ld"),RasEntry.dwfNetProtocols);
MessageBox(NULL,szError,_T("TROVO"),MB_OK | MB_ICONWARNING);
MessageBox(NULL,RasEntry.szScript,_T("szScript"),MB_OK | MB_ICONWARNING);
MessageBox(NULL,RasEntry.szAutoDialDll,_T("szAutoDialDll"),MB_OK | MB_ICONWARNING);
MessageBox(NULL,RasEntry.szAutoDialFunc,_T("szAutoDialFunc"),MB_OK | MB_ICONWARNING);
MessageBox(NULL,RasEntry.szDeviceType,_T("szDeviceType"),MB_OK | MB_ICONWARNING);
MessageBox(NULL,RasEntry.szDeviceName,_T("szDeviceName"),MB_OK | MB_ICONWARNING);
MessageBox(NULL,RasEntry.szX25PadType,_T("szX25PadType"),MB_OK | MB_ICONWARNING);
MessageBox(NULL,RasEntry.szAutoDialFunc,_T("szAutoDialFunc"),MB_OK | MB_ICONWARNING);
wsprintf(szError, _T("dwChannels")_T(" Error %ld"),RasEntry.dwChannels);
MessageBox(NULL,szError,_T("TROVO"),MB_OK | MB_ICONWARNING);
*/
}
wcscat(szTmp,lpRasEntry[dw].szEntryName);
wcscat(szTmp,_T("\n"));
}
wcscpy(lpstr,szTmp);
}
delete [] lpRasEntry;
return dwRes;
}
DWORD WINAPI RasEnumDev(LPWSTR lpstr) {
DWORD lpcb = 0 , lpcDevices, nRet, dw;
WCHAR szTmp[255];
LPRASDEVINFOW lpRasDevInfo = NULL;
RasEnumDevices(lpRasDevInfo, &lpcb, &lpcDevices);
lpRasDevInfo = (LPRASDEVINFOW) GlobalAlloc(GPTR, lpcb);
lpRasDevInfo->dwSize = sizeof(RASDEVINFOW);
nRet = RasEnumDevices(lpRasDevInfo, &lpcb, &lpcDevices);
/* debug only
// convert long to string
_ltow(lpcDevices, szTmp, 10);
MessageBox(NULL,szTmp,_T("Connexions"),MB_OK | MB_ICONWARNING);
*/
// initialisation de la variable temporaire szTmp
wcscpy(szTmp,_T(""));
if (nRet !=0) {
MessageBox(NULL,_T("RasEnumDevices failed"),_T("Connexions"),MB_OK | MB_ICONWARNING);
}
else {
for (dw = 0; dw < lpcDevices; dw++) {
wcscat(szTmp, lpRasDevInfo->szDeviceName);
wcscat(szTmp,_T("\n"));
MessageBox(NULL,szTmp,_T("Connexions"),MB_OK | MB_ICONWARNING);
lpRasDevInfo++;
}
wcscpy(lpstr,szTmp);
}
return nRet;
}
DWORD WINAPI CreateRasEntry(LPWSTR lpszName, LPWSTR lpszLogin, LPWSTR lpszPassword, LPWSTR lpszDeviceName) {
DWORD dwSize,
dwDevInfo = 280 /* 128 */,
dwError = 0;
//PDEVCFG pDevCfg;
TCHAR szError[100];
RASENTRY RasEntry;
RASIPADDR ipaddrDns ;
ipaddrDns.a = 145;
ipaddrDns.b = 130;
ipaddrDns.c = 233;
ipaddrDns.d = 10;
RASDIALPARAMS RasDialParams;
// Validate the format of a connection entry name
//
if (dwError = RasValidateEntryName(NULL, lpszName)) {
wsprintf(szError, _T("Unable to validate entry name.")_T(" Error %ld"),dwError);
MessageBox(NULL,szError,_T("Create Entry"),MB_OK | MB_ICONWARNING);
return dwError;
}
// initialize the RASENTRY structure
//
memset(&RasEntry,0,sizeof(RASENTRY));
dwSize = sizeof(RASENTRY);
RasEntry.dwSize = dwSize;
// Retrieve the entry properties
if (dwError = RasGetEntryProperties(NULL, _T(""), &RasEntry, &dwSize, NULL, NULL)) {
wsprintf(szError, _T("Unable to read default entry properties.")_T(" Error %ld"),dwError);
MessageBox(NULL,szError,_T("Create Entry"),MB_OK | MB_ICONWARNING);
return dwError;
}
// Fill the RASENTRY structure
//
// _tcscpy(RasEntry.szAreaCode, _T("\0"));
RasEntry.dwCountryID=(DWORD) 0;
// RasEntry.dwCountryCode = (DWORD) 0;
//_tcscpy(RasEntry.szAreaCode, lpszAreaCode);
RasEntry.dwCountryCode = (DWORD) 0;
_tcscpy(RasEntry.szLocalPhoneNumber, _T("~GPRS!rfi.tim.it"));
_tcscpy(RasEntry.szDeviceType, RASDT_Modem);
//_tcscpy(RasEntry.szDeviceName, _T("GSM Modem on COM2:"));
_tcscpy(RasEntry.szDeviceName, lpszDeviceName);
// RasEntry.dwfOptions = RASEO_UseCountryAndAreaCodes;
RasEntry.dwfOptions = RASEO_SpecificNameServers ;
RasEntry.dwAlternatesOffset=(DWORD) 1;
RasEntry.ipaddrDns = ipaddrDns;
RasEntry.dwfNetProtocols = (DWORD) 4;
RasEntry.dwFramingProtocol=RASFP_Ppp;
//memcpy( &(RasEntry.ipaddrDns), &RasEntry, sizeof( RASIPADDR ) );
// Create a new phone-book entry.
if (dwError = RasSetEntryProperties(NULL, lpszName, &RasEntry,sizeof(RASENTRY), (LPBYTE)lpDevCfg + lpDevCfg->dwStringOffset, lpDevCfg->dwStringSize)) {
//wsprintf(szError, _T("Unable to create the phone-book entry.")_T(" Error %ld"),dwError);
//MessageBox(NULL,szError,_T("Create Entry"),MB_OK | MB_ICONWARNING);
LocalFree(lpDevCfg);
return dwError;
}
LocalFree(lpDevCfg);
// Initialize a RASDIALPARAMS structure
//
memset(&RasDialParams,0,sizeof(RASDIALPARAMS));
RasDialParams.dwSize = sizeof(RASDIALPARAMS);
_tcscpy(RasDialParams.szEntryName, lpszName);
// Insert code here to fill up the RASDIALPARAMS structure
// RasDialParams.szPhoneNumber, lpszPhoneNumber;
// RasDialParams.szCallbackNumber[0], _T("\0");
RasDialParams.szPhoneNumber[0]=NULL;
RasDialParams.szCallbackNumber[0]=NULL;
wcscpy(RasDialParams.szUserName,lpszLogin);
wcscpy(RasDialParams.szPassword,lpszPassword);
wcscpy(RasDialParams.szDomain,TEXT("rfi.tim.it"));
// _tcscpy(RasDialParams.szUserName, lpszLogin);
// _tcscpy(RasDialParams.szPassword, lpszPassword);
// Change the connection data
//
if (dwError = RasSetEntryDialParams(NULL, &RasDialParams, FALSE)) {
//wsprintf(szError, _T("Unable to create the phone-book entry.")_T(" Error %ld"),dwError);
//MessageBox(NULL,szError,_T("Create Entry"),MB_OK | MB_ICONWARNING);
return dwError;
}
return dwError;
}
// ----------------------------------------------------------------
// (FIN) FONCTIONS CONCERNANT LA CREATION/DESTRUCTION D'ENTREES RAS
// ----------------------------------------------------------------
// -------------------------------------------------
// (DEBUT) FONCTIONS CONCERNANT LA BASE DE REGISTRES
// -------------------------------------------------
DWORD WriteKey()
{
//{ADB0B001-10B5-3F39-27C6-9742E785FCD4} = DestId (param internet)
//{18AD9FBD-F716-ACB6-FD8A-1965DB95B814} (param travail)
HKEY RegKey;
DWORD dwDisposition;
// Ouverture de la clé racine HKCU/Software
// if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\ConnMgr\\Providers\\{7C4B7A38-5FF7-4bc1-80F6-5DA7870BB1AA}\\Connections"), 0, 0, &RegKey)==ERROR_SUCCESS)
if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\ConnMgr\\Providers\\{7C4B7A38-5FF7-4bc1-80F6-5DA7870BB1AA}\\Connections"), 0, TEXT(""), 0, 0, NULL, &RegKey,
&dwDisposition)==ERROR_SUCCESS)
{
HKEY WorkKey;
DWORD dwDisposition;
// Création ou ouverture de la clé MyRegistryKey
if (RegCreateKeyEx (RegKey, TEXT("RFI"), 0, TEXT(""), 0, 0, NULL, &WorkKey,
&dwDisposition)==ERROR_SUCCESS)
{
TCHAR Key[32], Value[64];
wsprintf (Key, TEXT("DestId"));
wsprintf (Value, TEXT("{ADB0B001-10B5-3F39-27C6-9742E785FCD4}"));
RegSetValueEx (WorkKey, Key, 0, REG_SZ, (BYTE *)Value, lstrlen(Value)*sizeof(TCHAR));
DWORD dwValue;
wsprintf(Key, TEXT("RequirePw"));
dwValue=1;
RegSetValueEx (WorkKey, Key, 0, REG_DWORD, (BYTE *)&dwValue, sizeof(DWORD));
wsprintf(Key, TEXT("Enabled"));
dwValue=1;
RegSetValueEx (WorkKey, Key, 0, REG_DWORD, (BYTE *)&dwValue, sizeof(DWORD));
wsprintf(Key, TEXT("EntryType"));
dwValue=0;
RegSetValueEx (WorkKey, Key, 0, REG_DWORD, (BYTE *)&dwValue, sizeof(DWORD));
RegCloseKey(WorkKey);
if (debug==TRUE)
{
MessageBox(NULL, _T("RAS entry added in registry."), _T("DBG:RegCreateKeyEx"), MB_OK);
}
}
else
{
if (showErr==TRUE)
{
MessageBox(NULL, _T("Error while adding RAS entry in registry"), _T("ERROR:RegCreateEntryEx"), MB_OK);
}
}
RegCloseKey(RegKey);
}
return 0;
}
DWORD DeleteKey()
{
//{ADB0B001-10B5-3F39-27C6-9742E785FCD4} = DestId (param internet)
//{18AD9FBD-F716-ACB6-FD8A-1965DB95B814} (param travail)
DWORD ret=NULL;
ret=RegDeleteKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\ConnMgr\\Providers\\{7C4B7A38-5FF7-4bc1-80F6-5DA7870BB1AA}\\Connections\\RFI"));
if (ret==ERROR_SUCCESS)
{
if (debug==TRUE)
{
MessageBox(NULL, _T("Key successfully deleted."), _T("JAHLIGHT IR connect"), MB_OK);
}
}
else
{
if (showErr==TRUE)
{
TCHAR szMess[128];
if (ret!=87) wsprintf(szMess, _T("ERROR: Key not deleted, Error code=%ld"), ret);
else wsprintf(szMess, _T("RegDeleteKey:ERROR_INVALID_PARAMETER"));
MessageBox(NULL, szMess, _T("ERROR:RegDeleteKey"), MB_OK);
}
}
return 0;
}
// -------------------------------------------------
// (FIN) FONCTIONS CONCERNANT LA BASE DE REGISTRES
// -------------------------------------------------
Thank's in advance
CREATE RAS ENTRY
Why don't work :? :? :? :? :?
DWORD WINAPI CreateRasEntry(LPWSTR lpszName, LPWSTR lpszLogin, LPWSTR lpszPassword) {
DWORD dwSize,
dwDevInfo = 280 /* 128 */,
dwError = 0;
//PDEVCFG pDevCfg;
TCHAR szError[100];
RASENTRY RasEntry;
RASIPADDR ipaddrDns ;
RASDIALPARAMS RasDialParams;
// Validate the format of a connection entry name
//
if (dwError = RasValidateEntryName(NULL, lpszName)) {
return dwError;
}
// initialize the RASENTRY structure
//
memset(&RasEntry,0,sizeof(RASENTRY));
dwSize = sizeof(RASENTRY);
RasEntry.dwSize = dwSize;
// Retrieve the entry properties
if (dwError = RasGetEntryProperties(NULL, _T(""), &RasEntry, &dwSize, NULL, NULL)) {
return dwError;
}
// Fill the RASENTRY structure
//
ipaddrDns.a = 145;
ipaddrDns.b = 130;
ipaddrDns.c = 233;
ipaddrDns.d = 10;
_tcscpy(RasEntry.szDeviceType, RASDT_Vpn);
_tcscpy(RasEntry.szDeviceName, _T("Cellular Line (GPRS)"));
RasEntry.dwfOptions = RASEO_SpecificNameServers ;
RasEntry.ipaddrDns = ipaddrDns;
// Create a new phone-book entry.
if (dwError = RasSetEntryProperties(NULL, lpszName, &RasEntry,sizeof(RASENTRY), (LPBYTE)lpDevCfg + lpDevCfg->dwStringOffset, lpDevCfg->dwStringSize)) {
LocalFree(lpDevCfg);
return dwError;
}
LocalFree(lpDevCfg);
// Initialize a RASDIALPARAMS structure
//
memset(&RasDialParams,0,sizeof(RASDIALPARAMS));
RasDialParams.dwSize = sizeof(RASDIALPARAMS);
_tcscpy(RasDialParams.szEntryName, lpszName);
// Insert code here to fill up the RASDIALPARAMS structure
wcscpy(RasDialParams.szUserName,lpszLogin);
wcscpy(RasDialParams.szPassword,lpszPassword);
// Change the connection data
//
if (dwError = RasSetEntryDialParams(NULL, &RasDialParams, FALSE)) {
return dwError;
}
return dwError;
}
Hi friends.
I must solve big problem to finish HaRET (and other native applications) managed wrapper and UI (i. e. for example managed Silverlight UI controlled from unmanaged code), safe WP7 FTP client, interprocess cooperation on WP7, etc.
I know it is a basic issue, which is probably solved many time in operating systems (windows messages etc.) and many other examples.
But, I could find no any source code for queue, which is:
1. safe for more writers (threads from more processes) and for one reader,
2. unblocking for all writers,
3. unblocking for reader.
I found only very much unblocking ringbuffers or blocking queues, no one unblocking unlimited queue. Please, send corrections if I am bad looking.
Then, I tried code it...
First I want use std::queue with Thread Local Storage identifications (one subqueue for all writer and one abqueue for reader). But, TLS is very limited on CE based systems and I am not sure, if it solve interprocess safety too.
Finally, I tried to write the following code. It is designed for interthread queue only still, but interprocess can be added by safe named filemapping probably. Tell your opinion, it will be the basis for many complex applications here. For many years I have not worked with low-level synchronisation, I could make a fundamental mistake. So far I've missed templates and any wrapper, it's just the basic idea, usable in both C/C++ with very little changes:
PHP:
// This queue is unblocking and thread safe, when:
// 1. more writers are allowed,
// 2. one reader is allowed only.
// Motto: Pointers queue is both-directional, but frontal direction is changed by writers, backward direction by reader only!
#ifndef InterlockedExchangePointer
#define InterlockedExchangePointer(Target, Value) ((PVOID)InterlockedExchange((PLONG)(Target), (LONG)(Value)))
#endif
#ifndef InterlockedCompareExchangePointer
#define InterlockedCompareExchangePointer(Destination, ExChange, Comperand) ((PVOID)InterlockedCompareExchange((PLONG)(Destination), (LONG)(ExChange), (LONG)(Comperand)))
#endif
typedef struct SQItem
{
SQItem * pNext;
SQItem * pPrev;
void * pValue;
} * PItem;
SQItem EmptyItem = {NULL, NULL, NULL};
PItem pFront = &EmptyItem;
PItem pBack = &EmptyItem;
// Empty queue contains one item with both directions pointers nulled.
bool push_front(void * pNewValue) // nonblocking push, but theoretically forever cycle is possible for low priority thread! Practically improbable.
{
if (!pNewValue)
{
return false;
}
PItem pNewFront = new SQItem;
if (pNewFront)
{
PItem pProbablyFront;
InterlockedExchangePointer(&pProbablyFront, pFront);
pNewFront->pNext = pProbablyFront;
pNewFront->pPrev = NULL;
pNewFront->pValue = pNewValue;
while (InterlockedCompareExchangePointer(&pFront, pNewFront, pProbablyFront) != pProbablyFront)
{ // Another writer changed front pointer, active writer must try it again.
InterlockedExchangePointer(&pProbablyFront, pFront);
pNewFront->pNext = pProbablyFront;
}
return true; // Success allways.
}
return false; // Insufficient memory.
}
void * pop_back() // one reader allowed only!!!
{
PItem pBackward;
InterlockedExchangePointer(&pBackward, pFront); // Safe copy of actual front pointer
if (pBackward == pBack) // Queue is empty in time of interlocked attempt.
{
return NULL;
}
if (!pBack->pPrev)
{ // If backward queue is not continued here, reconstruct it from safe front pointer.
while (pBackward != pBack && !pBackward->pNext->pPrev)
{
pBackward->pNext->pPrev = pBackward;
pBackward = pBackward->pNext;
}
}
// One reader can safe read from back and manipulate with backward queue.
PItem pDelete = pBack;
pBack->pPrev->pNext = NULL;
pBack = pBack->pPrev;
delete pDelete;
return pBack->pValue;
/* // This is not necessary, but it is more clean:
void * pResult = pBack->pValue;
pBack->pValue = NULL;
return pResult;
*/
}
I am not sure, if heap allocation is not more "blocking" operation due to swapping and mm priorities, then object/signal waiting. What do you mean about it?
Mirror principle can be used to OneToMore queue making. Thanks unblocking, MoreToOne and OneToMore can be immeditelly piped to MoreToMore one.
But, when CE systems do not support two coupled pointers interlocked functions, there is no possibility to identify allowed reader safely, then this has not great significance.
As well, MoreToOne is much more needed now.
Template version
Using (simple example, the same way will be used between native threads and managed Silverlight UI):
Code:
#include "..\Templates\STQueue.h"
STQueue<tstring> qMessages(L"");
Code:
... // Called by [B]any thread[/B]:
void SafeMessage(tstring sMessage)
{
qMessages.push_front(sMessage);
PostMessage(hUnsafe, WM_FTP_MESSAGE, 0 , 0);
}
...
Code:
... // In UI thread:
LRESULT OnMsgMessage(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
bool bChange = false;
tstring szMessage = L"";
while ((szMessage = qMessages.pop_back()) != L"")
{
szMessages += szMessage;
szMessages += L"\r\n";
bChange = true;
}
if (bChange)
{
SetDlgItemText(hMainDlg, IDC_EDITMessage, szMessages.c_str());
}
return TRUE;
}
...
STQueue.h:
PHP:
template <class _Type> class STQItem
{
public:
STQItem<_Type> * pNext;
STQItem<_Type> * pPrev;
_Type Value;
STQItem(_Type & rV, STQItem<_Type> * pN = NULL, STQItem<_Type> * pP = NULL);
};
template <class _Type> class STQueue
{
protected:
STQItem<_Type> * pFront;
STQItem<_Type> * pBack;
_Type EmptyValue;
public:
STQueue(_Type EmptyV);
~STQueue();
bool push_front(const _Type & rNewValue);
const _Type & pop_back();
bool empty();
};
template <class _Type> STQItem<_Type>::STQItem(_Type & rV, STQItem<_Type> * pN, STQItem<_Type> * pP)
{
Value = rV;
pNext = pN;
pPrev = pP;
}
template <class _Type> STQueue<_Type>::STQueue(_Type EmptyV)
{
EmptyValue = EmptyV;
STQItem<_Type> * EmtyItem = new STQItem<_Type>(EmptyValue);
pFront = EmtyItem;
pBack = EmtyItem;
}
template <class _Type> STQueue<_Type>::~STQueue()
{
while (pop_back() != EmptyValue)
{
}
delete pBack;
}
template <class _Type> bool STQueue<_Type>::push_front(const _Type & rNewValue)
{ // nonblocking push, but theoretically forever cycle is possible for low priority thread!
STQItem<_Type> * pNewFront = new STQItem<_Type>(EmptyValue);
if (pNewFront)
{
STQItem<_Type> * pProbablyFront;
InterlockedExchangePointer(&pProbablyFront, pFront);
pNewFront->pNext = pProbablyFront;
pNewFront->pPrev = NULL;
pNewFront->Value = rNewValue;
while (InterlockedCompareExchangePointer(&pFront, pNewFront, pProbablyFront) != pProbablyFront)
{ // Another writer changed front pointer, active writer must try it again.
InterlockedExchangePointer(&pProbablyFront, pFront);
pNewFront->pNext = pProbablyFront;
}
return true; // Success allways.
}
return false; // Insufficient memory.
}
template <class _Type> const _Type & STQueue<_Type>::pop_back()
{ // one reader allowed only!!!
STQItem<_Type> * pBackward;
InterlockedExchangePointer(&pBackward, pFront); // Safe copy of actual front pointer
if (pBackward == pBack) // Queue is empty in time of interlocked attempt.
{
return EmptyValue;
}
if (!pBack->pPrev)
{ // If backward queue is not beginned, reconstruct it from safe front pointer.
while (pBackward != pBack && !pBackward->pNext->pPrev)
{
pBackward->pNext->pPrev = pBackward;
pBackward = pBackward->pNext;
}
}
// One reader can safe read from back and manipulate with backward queue.
STQItem<_Type> * pDelete = pBack;
pBack->pPrev->pNext = NULL;
pBack = pBack->pPrev;
delete pDelete;
return pBack->Value;
/* // This is not necessary, but it is more clean:
void * pResult = pBack->pValue;
pBack->pValue = NULL;
return pResult;
*/
}
template <class _Type> bool STQueue<_Type>::empty()
{
if(last==NULL)
return TRUE;
else
return FALSE;
}