windows-nt/Source/XPSP1/NT/net/rras/ras/autodial/rasautou/rasautou.c
2020-09-26 16:20:57 +08:00

1376 lines
34 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#define UNICODE
#define _UNICODE
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <npapi.h>
#include <winsock.h>
#include <wsnetbs.h>
#include <ras.h>
#include <raserror.h>
#include <rasdlg.h>
#include <tapi.h>
#include <commctrl.h> // added to be "Fusionized"
#include <shfusion.h> // added to be "Fusionized"
#include "process.h"
//
// Whistler bug 293751 rasphone.exe / rasautou.exe need to be "Fusionized" for
// UI conistency w/Connections Folder
//
HANDLE g_hModule = NULL;
//
// All projection types. Used to
// determine if a connection was
// completed.
//
#define MAX_PROJECTIONS 5
struct RASPROJECTIONINFO {
DWORD dwTag;
DWORD dwSize;
} projections[MAX_PROJECTIONS] = {
RASP_Amb, sizeof (RASAMB),
RASP_PppNbf, sizeof (RASPPPNBF),
RASP_PppIpx, sizeof (RASPPPIPX),
RASP_PppIp, sizeof (RASPPPIP),
RASP_PppLcp, sizeof (RASPPPLCP)
};
//
// Timer thread information.
//
typedef struct _TIMER_INFO {
HANDLE hEvent;
DWORD dwTimeout;
} TIMER_INFO, *PTIMER_INFO;
//
// Private rasdlg functions.
//
DWORD
RasAutodialQueryDlgW(
IN HWND hwnd,
IN PWCHAR pszAddress,
IN PWCHAR pszEntry,
IN DWORD dwTimeout,
OUT PWCHAR pszEntrySelectedByUser
);
BOOLEAN
RasAutodialDisableDlgW(
HWND hwnd
);
PSYSTEM_PROCESS_INFORMATION
GetSystemProcessInfo()
/*++
DESCRIPTION
Return a block containing information about all processes
currently running in the system.
ARGUMENTS
None.
RETURN VALUE
A pointer to the system process information or NULL if it could
not be allocated or retrieved.
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PUCHAR pLargeBuffer;
ULONG ulcbLargeBuffer = 64 * 1024;
//
// Get the process list.
//
for (;;) {
pLargeBuffer = VirtualAlloc(
NULL,
ulcbLargeBuffer, MEM_COMMIT, PAGE_READWRITE);
if (pLargeBuffer == NULL) {
printf(
"GetSystemProcessInfo: VirtualAlloc failed (status=0x%x)\n",
status);
return NULL;
}
status = NtQuerySystemInformation(
SystemProcessInformation,
pLargeBuffer,
ulcbLargeBuffer,
NULL);
if (status == STATUS_SUCCESS) break;
if (status == STATUS_INFO_LENGTH_MISMATCH) {
VirtualFree(pLargeBuffer, 0, MEM_RELEASE);
ulcbLargeBuffer += 8192;
}
}
return (PSYSTEM_PROCESS_INFORMATION)pLargeBuffer;
} // GetSystemProcessInfo
PSYSTEM_PROCESS_INFORMATION
FindProcessByName(
IN PSYSTEM_PROCESS_INFORMATION pProcessInfo,
IN LPWSTR lpExeName
)
/*++
DESCRIPTION
Given a pointer returned by GetSystemProcessInfo(), find
a process by name.
ARGUMENTS
pProcessInfo: a pointer returned by GetSystemProcessInfo().
lpExeName: a pointer to a Unicode string containing the
process to be found.
RETURN VALUE
A pointer to the process information for the supplied
process or NULL if it could not be found.
--*/
{
PUCHAR pLargeBuffer = (PUCHAR)pProcessInfo;
ULONG ulTotalOffset = 0;
//
// Look in the process list for lpExeName.
//
for (;;) {
if (pProcessInfo->ImageName.Buffer != NULL) {
if (!_wcsicmp(pProcessInfo->ImageName.Buffer, lpExeName))
return pProcessInfo;
}
//
// Increment offset to next process information block.
//
if (!pProcessInfo->NextEntryOffset)
break;
ulTotalOffset += pProcessInfo->NextEntryOffset;
pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&pLargeBuffer[ulTotalOffset];
}
return NULL;
} // FindProcessByName
VOID
FreeSystemProcessInfo(
IN PSYSTEM_PROCESS_INFORMATION pProcessInfo
)
/*++
DESCRIPTION
Free a buffer returned by GetSystemProcessInfo().
ARGUMENTS
pProcessInfo: the pointer returned by GetSystemProcessInfo().
RETURN VALUE
None.
--*/
{
VirtualFree((PUCHAR)pProcessInfo, 0, MEM_RELEASE);
} // FreeSystemProcessInfo
DWORD
ActiveConnections()
{
DWORD dwErr, dwcbConnections = 0, dwcConnections = 0;
DWORD i, j, dwTmp, dwSize;
RASCONN rasconn;
LPRASCONN lpRasCon = &rasconn;
RASCONNSTATUS rasconnstatus;
//
// Determine how much memory we
// need to allocate.
//
lpRasCon->dwSize = sizeof (RASCONN);
dwErr = RasEnumConnections(lpRasCon, &dwcbConnections, &dwcConnections);
if (dwErr == ERROR_BUFFER_TOO_SMALL) {
lpRasCon = LocalAlloc(LPTR, dwcbConnections);
if (lpRasCon == NULL)
return 0;
//
// Call again to fill the buffer.
//
lpRasCon->dwSize = sizeof (RASCONN);
dwErr = RasEnumConnections(lpRasCon, &dwcbConnections, &dwcConnections);
}
if (dwErr)
goto done;
dwTmp = dwcConnections;
for (i = 0; i < dwTmp; i++) {
rasconnstatus.dwSize = sizeof (RASCONNSTATUS);
dwErr = RasGetConnectStatus(
lpRasCon[i].hrasconn,
&rasconnstatus);
if (dwErr || rasconnstatus.rasconnstate != RASCS_Connected)
dwcConnections--;
}
done:
if (lpRasCon != &rasconn)
LocalFree(lpRasCon);
return dwErr ? 0 : dwcConnections;
} // ActiveConnections
void
TapiLineCallback(
IN DWORD hDevice,
IN DWORD dwMessage,
IN ULONG_PTR dwInstance,
IN ULONG_PTR dwParam1,
IN ULONG_PTR dwParam2,
IN ULONG_PTR dwParam3
)
{
} // TapiLineCallback
DWORD
GetCurrentDialingLocation()
{
DWORD dwErr, dwcDevices, dwLocationID;
HLINEAPP hlineApp;
LINETRANSLATECAPS caps;
LINETRANSLATECAPS *pCaps;
//
// Initialize TAPI.
//
dwErr = lineInitialize(
&hlineApp,
GetModuleHandle(NULL),
TapiLineCallback,
NULL,
&dwcDevices);
if (dwErr)
return 0;
//
// Get the dialing location from TAPI.
//
RtlZeroMemory(&caps, sizeof (LINETRANSLATECAPS));
caps.dwTotalSize = sizeof (LINETRANSLATECAPS);
dwErr = lineGetTranslateCaps(hlineApp, 0x10004, &caps);
if (dwErr)
return 0;
pCaps = (LINETRANSLATECAPS *)LocalAlloc(LPTR, caps.dwNeededSize);
if (pCaps == NULL)
return 0;
RtlZeroMemory(pCaps, sizeof (LINETRANSLATECAPS));
pCaps->dwTotalSize = caps.dwNeededSize;
dwErr = lineGetTranslateCaps(hlineApp, 0x10004, pCaps);
if (dwErr) {
LocalFree(pCaps);
return 0;
}
dwLocationID = pCaps->dwCurrentLocationID;
LocalFree(pCaps);
//
// Shutdown TAPI.
//
dwErr = lineShutdown(hlineApp);
return dwLocationID;
} // GetCurrentDialingLocation
DWORD
TimerThread(
LPVOID lpArg
)
{
NTSTATUS status;
PTIMER_INFO pTimerInfo = (PTIMER_INFO)lpArg;
HANDLE hEvent = pTimerInfo->hEvent;
DWORD dwTimeout = pTimerInfo->dwTimeout;
LocalFree(pTimerInfo);
//
// Wait for the timeout period. If hEvent
// gets signaled before the timeout period
// expires, then the user has addressed the
// dialog and we return. Otherwise, we simply
// exit.
//
if (WaitForSingleObject(hEvent, dwTimeout * 1000) == WAIT_TIMEOUT)
exit(1);
return 0;
} // TimerThread
DWORD
DisplayRasDialog(
IN LPTSTR pszPhonebook,
IN LPTSTR pszEntry,
IN LPTSTR pszAddress,
IN BOOLEAN fRedialMode,
IN BOOLEAN fQuiet
)
{
NTSTATUS status;
DWORD dwErr = 0, dwSize, dwCount = 0;
DWORD dwcConnections, dwfDisableConnectionQuery;
DWORD dwPreDialingLocation, dwPostDialingLocation;
DWORD dwConnectionQueryTimeout;
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInfo;
PSYSTEM_PROCESS_INFORMATION pSystemInfo;
BOOLEAN fCancelled;
LPRASAUTODIALENTRY pAutodialEntries = NULL;
DWORD dwcbAutodialEntries = 0, dwcAutodialEntries = 0;
WCHAR pszNewEntry[RAS_MaxEntryName + 1];
wcscpy(pszNewEntry, L"\0");
//
// Check to see if the user has disabled
// the Autodial query dialog when the
// phonebook entry to dial is known.
//
if (fRedialMode || fQuiet)
dwfDisableConnectionQuery = TRUE;
else {
dwSize = sizeof (DWORD);
(void)RasGetAutodialParam(
RASADP_DisableConnectionQuery,
&dwfDisableConnectionQuery,
&dwSize);
}
//
// Ask the user if he wants to dial if either the
// phonebook entry is not known or the user has
// not disabled the "always ask me before dialing"
// parameter.
//
// If RasDialDlg() returns FALSE, the user didn't
// want to dial.
//
if (pszEntry == NULL || !dwfDisableConnectionQuery) {
dwSize = sizeof (DWORD);
(void)RasGetAutodialParam(
RASADP_ConnectionQueryTimeout,
&dwConnectionQueryTimeout,
&dwSize);
//
// Save the current dialing location to
// see if the user changed it inside the
// dialog.
//
dwPreDialingLocation = GetCurrentDialingLocation();
dwErr = RasAutodialQueryDlgW(
NULL, pszAddress, pszEntry, dwConnectionQueryTimeout, pszNewEntry);
// Whistler: 255816
//
// Only disable the address if an error occurs.
// If the user simply types 'no' then CANCEL is
// returned from rasdlg, but we'll return NO_ERROR to the
// rasauto service so that the address remains enabled.
//
if (dwErr == ERROR_CANCELLED)
{
return NO_ERROR;
}
else if (dwErr != NO_ERROR)
{
return ERROR_CANCELLED;
}
dwPostDialingLocation = GetCurrentDialingLocation();
//
// If the user changed the dialing location
// within the dialog, then get the new entry.
//
if (dwPreDialingLocation != dwPostDialingLocation) {
pszEntry = NULL;
dwErr = RasGetAutodialAddress(
pszAddress,
NULL,
NULL,
&dwcbAutodialEntries,
&dwcAutodialEntries);
if (dwErr == ERROR_BUFFER_TOO_SMALL && dwcAutodialEntries)
pAutodialEntries = LocalAlloc(LPTR, dwcbAutodialEntries);
if (dwcAutodialEntries && pAutodialEntries != NULL) {
pAutodialEntries[0].dwSize = sizeof (RASAUTODIALENTRY);
dwErr = RasGetAutodialAddress(
pszAddress,
NULL,
pAutodialEntries,
&dwcbAutodialEntries,
&dwcAutodialEntries);
if (!dwErr) {
DWORD i;
for (i = 0; i < dwcAutodialEntries; i++) {
if (pAutodialEntries[i].dwDialingLocation ==
dwPostDialingLocation)
{
pszEntry = pAutodialEntries[i].szEntry;
break;
}
}
}
}
}
// Whistler: new autodial UI
//
// The connection that the user wants to dial will be in
// pszNewEntry.
//
else
{
if (*pszNewEntry)
{
pszEntry = pszNewEntry;
}
}
}
if (pszEntry)
{
RASDIALDLG info;
ZeroMemory( &info, sizeof(info) );
info.dwSize = sizeof(info);
//
// Prevent the DialerDialog to come up only if the
// user has checked the don't query before dialing
// checkbox. Otherwise we bringup the dialog.
//
if(dwfDisableConnectionQuery)
{
info.dwFlags |= RASDDFLAG_NoPrompt;
}
if (fRedialMode)
{
/* Set this flag to tell RasDialDlg to popup the "reconnect
** pending" countdown dialog before redialing.
*/
info.dwFlags |= RASDDFLAG_LinkFailure;
}
/* Popup the "Dial-Up Networking" dialing dialogs.
*/
fCancelled = !RasDialDlg( pszPhonebook, pszEntry, NULL, &info );
}
else if (!fQuiet)
{
RASPBDLG info;
ZeroMemory( &info, sizeof(info) );
info.dwSize = sizeof(info);
info.dwFlags = RASPBDFLAG_ForceCloseOnDial;
/* Popup the main "Dial-Up Networking" dialog.
*/
fCancelled = !RasPhonebookDlg( pszPhonebook, NULL, &info );
}
if (!fRedialMode && !fQuiet && fCancelled)
{
/* User did not make a connection. Ask him if he wants to nix
** auto-dial for this location.
*/
// if (RasAutodialDisableDlgW( NULL ))
// RasSetAutodialEnable( GetCurrentDialingLocation(), FALSE );
}
if (pAutodialEntries != NULL)
LocalFree(pAutodialEntries);
return 0;
} // DisplayRasDialog
DWORD
GetExpandedDllPath(LPTSTR pszDllPath,
LPTSTR *ppszExpandedDllPath)
{
DWORD dwErr = 0;
DWORD dwSize = 0;
//
// find the size of the expanded string
//
if (0 == (dwSize =
ExpandEnvironmentStrings(pszDllPath,
NULL,
0)))
{
dwErr = GetLastError();
goto done;
}
*ppszExpandedDllPath = LocalAlloc(
LPTR,
dwSize * sizeof (TCHAR));
if (NULL == *ppszExpandedDllPath)
{
dwErr = GetLastError();
goto done;
}
//
// Get the expanded string
//
if (0 == ExpandEnvironmentStrings(
pszDllPath,
*ppszExpandedDllPath,
dwSize))
{
dwErr = GetLastError();
}
done:
return dwErr;
}
LPWSTR
ConvertToUnicodeString(
LPSTR psz
)
// Modified to use code from nouiutil
{
WCHAR* pszNew = NULL;
if (psz)
{
DWORD cb;
cb = MultiByteToWideChar( CP_ACP, 0, psz, -1, NULL, 0 );
ASSERT(cb);
pszNew = LocalAlloc( LPTR, (cb + 1) * sizeof(TCHAR) );
if (!pszNew)
{
printf("rasautou: LocalAlloc failed\n");
return NULL;
}
cb = MultiByteToWideChar( CP_ACP, 0, psz, -1, pszNew, cb );
if (cb == 0)
{
LocalFree( pszNew );
printf("rasautou: multibyte string conversion failed\n");
return NULL;
}
}
return pszNew;
} // ConvertToUnicodeString
LPSTR
ConvertToAnsiString(
PWCHAR psz
)
// Modified to use code from nouiutil
{
CHAR* pszNew = NULL;
if (psz)
{
DWORD cb;
cb = WideCharToMultiByte( CP_ACP, 0, psz, -1, NULL, 0, NULL, NULL );
ASSERT(cb);
pszNew = (CHAR* )LocalAlloc( LPTR, cb + 1 );
if (!pszNew)
{
printf("rasautou: LocalAlloc failed");
return NULL;
}
cb = WideCharToMultiByte( CP_ACP, 0, psz, -1, pszNew, cb, NULL, NULL );
if (cb == 0)
{
LocalFree( pszNew );
printf("rasautou: wide-character string conversion failed");
return NULL;
}
}
return pszNew;
} // ConvertToUnicodeString
DWORD
DisplayCustomDialog(
IN LPTSTR pszDll,
IN LPTSTR pszFunc,
IN LPTSTR pszPhonebook,
IN LPTSTR pszEntry,
IN LPTSTR pszAddress
)
{
DWORD dwErr, dwRetCode;
HINSTANCE hLibrary;
CHAR szFuncNew[64], szFuncOld[64], *pszOldFunc = NULL;
ORASADFUNC pfnOldStyleFunc;
RASADFUNC pfnFunc;
RASADPARAMS params;
LPTSTR pszExpandedPath = NULL;
CHAR * pszEntryA = NULL;
dwErr = GetExpandedDllPath(pszDll,
&pszExpandedPath);
if(ERROR_SUCCESS != dwErr)
{
return dwErr;
}
//
// Load the library.
//
hLibrary = LoadLibrary(pszExpandedPath);
if (hLibrary == NULL) {
dwErr = GetLastError();
printf(
"rasdlui: %s: AutoDial DLL cannot be loaded (dwErr=%d)\n",
pszDll,
dwErr);
LocalFree(pszExpandedPath);
return dwErr;
}
//
// Get the procedure address. First,
// we check for a new-style entry point,
// and then check for an old-style entry
// point if the new-style one doesn't exist.
//
#ifdef UNICODE
sprintf(szFuncNew, "%SW", pszFunc);
pszOldFunc = ConvertToAnsiString(pszFunc);
pszEntryA = ConvertToAnsiString(pszEntry);
if (!pszOldFunc || !pszEntryA)
{
printf("rasautou: Allocation failed. Exiting\n");
exit(1);
}
#else
sprintf(szFuncNew, "%sA", pszFunc);
strcpy(szFuncOld, pszFunc);
pszOldFunc = szFuncOld;
pszEntryA = pszEntry;
#endif
pfnFunc = (RASADFUNC)GetProcAddress(hLibrary, szFuncNew);
if (pfnFunc != NULL)
{
//
// Initialize the param block.
//
params.hwndOwner = NULL;
params.dwFlags = 0;
params.xDlg = params.yDlg = 0;
//params.dwCallbackId = 0;
//params.pCallback = NULL;
//
// Call the procedure.
//
(*pfnFunc)(pszPhonebook, pszEntry, &params, &dwRetCode);
}
else
{
pfnOldStyleFunc = (ORASADFUNC)GetProcAddress(hLibrary, pszOldFunc);
if (pfnOldStyleFunc != NULL)
{
(*pfnOldStyleFunc)(NULL, pszEntryA, 0, &dwRetCode);
}
else
{
#ifdef UNICODE
printf(
"rasautou: %S: Function cannot be loaded from AutoDial DLL %S\n",
pszDll,
pszFunc);
#else
printf(
"rasautou: %s: Function cannot be loaded from AutoDial DLL %s\n",
pszDll,
pszFunc);
#endif
exit(1);
}
}
//
// Clean up.
//
FreeLibrary(hLibrary);
#ifdef UNICODE
if (pszOldFunc)
{
LocalFree(pszOldFunc);
}
if (pszEntryA)
{
LocalFree(pszOldFunc);
}
#endif
LocalFree(pszExpandedPath);
return dwRetCode;
} // DisplayCustomDialog
VOID
FreeConvertedString(
IN LPWSTR pwsz
)
{
if (pwsz != NULL)
LocalFree(pwsz);
} // FreeConvertedString
BOOLEAN
RegGetValueA(
IN HKEY hkey,
IN LPSTR pszKey,
OUT PVOID *ppvData,
OUT LPDWORD pdwcbData
)
{
DWORD dwError, dwType, dwSize;
PVOID pvData;
//
// Get the length of the string.
//
dwError = RegQueryValueExA(
hkey,
pszKey,
NULL,
&dwType,
NULL,
&dwSize);
if (dwError != ERROR_SUCCESS)
return FALSE;
pvData = LocalAlloc(LPTR, dwSize);
if (pvData == NULL) {
DbgPrint("RegGetValueA: LocalAlloc failed\n");
return FALSE;
}
//
// Read the value for real this time.
//
dwError = RegQueryValueExA(
hkey,
pszKey,
NULL,
NULL,
(LPBYTE)pvData,
&dwSize);
if (dwError != ERROR_SUCCESS) {
LocalFree(pvData);
return FALSE;
}
*ppvData = pvData;
if (pdwcbData != NULL)
*pdwcbData = dwSize;
return TRUE;
} // RegGetValueA
VOID
NetworkConnected()
/*++
DESCRIPTION
Determine whether there exists some network connection.
Note: This code was stolen from sockit.c courtesy of ArnoldM.
ARGUMENTS
None
RETURN VALUE
TRUE if one exists, FALSE otherwise.
--*/
{
typedef struct _LANA_MAP {
BOOLEAN fEnum;
UCHAR bLana;
} LANA_MAP, *PLANA_MAP;
BOOLEAN fNetworkPresent = FALSE;
HKEY hKey;
PLANA_MAP pLanaMap = NULL, pLana;
DWORD dwError, dwcbLanaMap;
PCHAR pMultiSzLanasA = NULL, paszTemp;
DWORD dwcBindings, dwcMaxLanas, i, dwcbLanas;
LONG iLana;
DWORD dwZero = 0;
PCHAR *paszLanas = NULL;
SOCKET s;
SOCKADDR_NB nbaddress, nbsendto;
NTSTATUS status;
UNICODE_STRING deviceName;
OBJECT_ATTRIBUTES attributes;
IO_STATUS_BLOCK iosb;
HANDLE handle;
PWCHAR pwsz;
dwError = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
L"System\\CurrentControlSet\\Services\\Netbios\\Linkage",
0,
KEY_READ,
&hKey);
if (dwError != ERROR_SUCCESS) {
printf(
"NetworkConnected: RegKeyOpenEx failed (dwError=%d)\n",
GetLastError());
return;
}
//
// Read in the LanaMap.
//
if (!RegGetValueA(hKey, "LanaMap", &pLanaMap, &dwcbLanaMap)) {
printf("NetworkConnected: RegGetValueA(LanaMap) failed\n");
goto done;
}
dwcBindings = dwcbLanaMap / sizeof (LANA_MAP);
//
// Read in the bindings.
//
if (!RegGetValueA(hKey, "bind", &pMultiSzLanasA, &dwcbLanas)) {
printf("NetworkConnected: RegGetValueA(bind) failed\n");
goto done;
}
//
// Allocate a buffer for the binding array.
//
paszLanas = LocalAlloc(LPTR, (dwcBindings+1) * sizeof (PCHAR));
if (paszLanas == NULL) {
printf("NetworkConnected: LocalAlloc failed\n");
goto done;
}
//
// Parse the bindings into an array of strings.
//
for (dwcMaxLanas = 0, paszTemp = pMultiSzLanasA; *paszTemp; paszTemp++) {
paszLanas[dwcMaxLanas++] = paszTemp;
while(*++paszTemp);
}
//
// Finally enumerate the bindings and
// attempt to create a socket on each.
//
nbaddress.snb_family = AF_NETBIOS;
nbaddress.snb_type = 0;
memcpy(nbaddress.snb_name, "yahooyahoo ", 16);
nbsendto.snb_family = AF_NETBIOS;
nbsendto.snb_type = 0;
memcpy(nbsendto.snb_name, "billybob ", 16);
for (iLana = 0, pLana = pLanaMap; dwcBindings--; iLana++, pLana++) {
int iLanaMap = (int)pLana->bLana;
if (pLana->fEnum && (DWORD)iLana < dwcMaxLanas) {
int iError;
if (!_stricmp(paszLanas[iLana], "\\Device\\NwlnkNb") ||
strstr(paszLanas[iLana], "_NdisWan") != NULL)
{
printf("NetworkConnected: ignoring %s\n", paszLanas[iLana]);
continue;
}
#ifdef notdef
s = socket(AF_NETBIOS, SOCK_DGRAM, -iLanaMap);
if (s == INVALID_SOCKET) {
printf(
"NetworkConnected: socket(%s, %d) failed (error=%d)\n",
paszLanas[iLana],
iLana,
WSAGetLastError());
continue;
}
//printf("s=0x%x, iLana=%d, %s\n", s, iLana, paszLanas[iLana]);
iError = ioctlsocket(s, FIONBIO, &dwZero);
if (iError == SOCKET_ERROR) {
printf(
"NetworkConnected: ioctlsocket(%s) failed (error=%d)\n",
paszLanas[iLana],
iLana,
WSAGetLastError());
goto cleanup;
}
iError = bind(
s,
(struct sockaddr *)&nbaddress,
sizeof(nbaddress));
if (iError == SOCKET_ERROR) {
printf(
"NetworkConnected: bind(%s, %d) failed (error=%d)\n",
paszLanas[iLana],
iLana,
WSAGetLastError());
goto cleanup;
}
iError = sendto(
s,
(PCHAR)&nbsendto,
sizeof (nbsendto),
0,
(struct sockaddr *)&nbsendto,
sizeof (nbsendto));
if (iError == SOCKET_ERROR) {
printf(
"NetworkConnected: sendto(%s, %d) failed (error=%d)\n",
paszLanas[iLana],
iLana,
WSAGetLastError());
}
cleanup:
closesocket(s);
if (iError != SOCKET_ERROR) {
printf("NetworkConnected: network (%s, %d) is up\n",
paszLanas[iLana],
iLana);
fNetworkPresent = TRUE;
break;
}
#else
pwsz = ConvertToUnicodeString(paszLanas[iLana]);
RtlInitUnicodeString(&deviceName, pwsz);
InitializeObjectAttributes(
&attributes,
&deviceName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
status = NtOpenFile(&handle, READ_CONTROL, &attributes, &iosb, 0, 0);
NtClose(handle);
LocalFree(pwsz);
if (NT_SUCCESS(status)) {
printf(
"NetworkConnected: network (%s, %d) is up\n",
paszLanas[iLana],
iLana);
fNetworkPresent = TRUE;
break;
}
else {
printf(
"NetworkConnected: NtOpenFile on %s failed (status=0x%x)\n",
paszLanas[iLana],
status);
}
#endif
}
}
//
// Free resources.
//
done:
if (paszLanas != NULL)
LocalFree(paszLanas);
if (pMultiSzLanasA != NULL)
LocalFree(pMultiSzLanasA);
if (pLanaMap != NULL)
LocalFree(pLanaMap);
RegCloseKey(hKey);
} // NetworkConnected
VOID
DumpAutoDialAddresses()
{
DWORD dwErr, i, dwcb, dwcAddresses;
LPTSTR *lppAddresses = NULL;
dwErr = RasEnumAutodialAddresses(NULL, &dwcb, &dwcAddresses);
if (dwErr && dwErr != ERROR_BUFFER_TOO_SMALL) {
printf("RasEnumAutodialAddresses failed (dwErr=%d)\n", dwErr);
return;
}
if (dwcAddresses) {
lppAddresses = (LPTSTR *)LocalAlloc(LPTR, dwcb);
if (lppAddresses == NULL) {
printf("LocalAlloc failed\n");
return;
}
dwErr = RasEnumAutodialAddresses(lppAddresses, &dwcb, &dwcAddresses);
if (dwErr) {
printf("RasEnumAutodialAddresses failed (dwErr=%d)\n", dwErr);
LocalFree(lppAddresses);
return;
}
}
printf("There are %d Autodial addresses:\n", dwcAddresses);
for (i = 0; i < dwcAddresses; i++)
#ifdef UNICODE
printf("%S\n", lppAddresses[i]);
#else
printf("%s\n", lppAddresses[i]);
#endif
if (lppAddresses != NULL)
LocalFree(lppAddresses);
} // DumpAutoDialAddresses
VOID
DumpStatus()
{
DWORD dwErr;
WSADATA wsaData;
//
// Initialize winsock.
//
dwErr = WSAStartup(MAKEWORD(2,0), &wsaData);
if (dwErr) {
DbgPrint("AcsInitialize: WSAStartup failed (dwErr=%d)\n", dwErr);
return;
}
//
// Display network connectivity.
//
printf("Checking netcard bindings...\n");
NetworkConnected();
//
// Display AutoDial address table.
//
printf("\nEnumerating AutoDial addresses...\n");
DumpAutoDialAddresses();
} // DumpStatus
// Returns true if a redial-on-link-failure process is
// active.
//
BOOL
OtherRasautouExists(
IN PSYSTEM_PROCESS_INFORMATION pProcessInfo)
{
PUCHAR pLargeBuffer = (PUCHAR)pProcessInfo;
ULONG ulTotalOffset = 0;
DWORD dwProcId, dwSessId = 0;
BOOL fValidSessId = FALSE;
dwProcId = GetCurrentProcessId();
fValidSessId = ProcessIdToSessionId(dwProcId, &dwSessId);
//printf(
// "ProcId=%d, SessId=%d, ValSess=%d\n", dwProcId, dwSessId, fValidSessId);
//
// Look in the process list for lpExeName.
//
for (;;)
{
if (pProcessInfo->ImageName.Buffer != NULL)
{
// If
// 1. The process is in our session
// 2. It is not us
// 3. It is rasautou
//
// Then another rasautou is already active -- we should
// return success so that no ui is raised.
//
//printf(
// "id=%-2d, sess=%-4d, %S\n",
// PtrToUlong(pProcessInfo->UniqueProcessId),
// pProcessInfo->SessionId,
// pProcessInfo->ImageName.Buffer);
if (
((dwSessId == pProcessInfo->SessionId) || (!fValidSessId)) &&
(PtrToUlong(pProcessInfo->UniqueProcessId) != dwProcId) &&
(_wcsicmp(pProcessInfo->ImageName.Buffer, L"rasautou.exe") == 0)
)
{
//
// We could actually check that
// 4. That rasautou function is started with the -r flag
//
// However, it doesn't hurt to return if this is any rasautou
// prompt.
//
return TRUE;
}
}
//
// Increment offset to next process information block.
//
if (!pProcessInfo->NextEntryOffset)
{
break;
}
ulTotalOffset += pProcessInfo->NextEntryOffset;
pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&pLargeBuffer[ulTotalOffset];
}
return FALSE;
} // FindProcessByName
//
// Determines whether any redial on link failure prompts are
// currently active.
//
BOOL
OtherRasautouActive()
{
BOOL bRet = FALSE;
PSYSTEM_PROCESS_INFORMATION pSysInfo = NULL;
do
{
// Discover the processes on the system
//
pSysInfo = GetSystemProcessInfo();
if (pSysInfo == NULL)
{
break;
}
// Find out if any rasautou processes are active
//
bRet = OtherRasautouExists(pSysInfo);
} while (FALSE);
// Cleanup
//
{
if (pSysInfo)
{
FreeSystemProcessInfo(pSysInfo);
}
}
//printf("OtherRasautouActive() returned %s", (bRet) ? "true" : "false");
return bRet;
}
VOID _cdecl
wmain(
INT argc,
WCHAR **argv
)
{
DWORD dwErr = 0;
BOOLEAN fStatusFlag = FALSE, fRedialFlag = FALSE, fQuiet = FALSE;
PWCHAR pszPhonebookArg, pszEntryArg, pszDllArg, pszFuncArg, pszAddressArg;
LPTSTR pszPhonebook, pszEntry, pszDll, pszFunc, pszAddress;
//
// Whistler bug 293751 rasphone.exe / rasautou.exe need to be "Fusionized"
// for UI conistency w/Connections Folder
//
if (g_hModule = GetModuleHandle( NULL )) {
SHFusionInitializeFromModule( g_hModule );
}
if (argc < 2) {
usage:
printf(
"Usage: rasautou [-f phonebook] [-d dll -p proc] [-a address] [-e entry] [-s]\n");
exit(1);
}
//
// Initialize the command line argument pointers.
//
pszPhonebookArg = NULL;
pszEntryArg = NULL;
pszDllArg = NULL;
pszFuncArg = NULL;
pszAddressArg = NULL;
//
// Crack command line parameters.
//
while (--argc && argv++) {
if (**argv != L'-')
break;
switch ((*argv)[1]) {
case L'a':
argc--;
if (!argc)
goto usage;
pszAddressArg = *(++argv);
break;
case L'd':
argc--;
if (!argc)
goto usage;
pszDllArg = *(++argv);
break;
case L'e':
argc--;
if (!argc)
goto usage;
pszEntryArg = *(++argv);
break;
case L'f':
argc--;
if (!argc)
goto usage;
pszPhonebookArg = *(++argv);
break;
case L'p':
argc--;
if (!argc)
goto usage;
pszFuncArg = *(++argv);
break;
case L'q':
fQuiet = TRUE;
break;
case L'r':
fRedialFlag = TRUE;
break;
case L's':
fStatusFlag = TRUE;
break;
default:
goto usage;
}
}
//
// If either the DLL name or the function
// name is missing, then display usage.
//
if ((pszDllArg == NULL) != (pszFuncArg == NULL) && !fStatusFlag)
goto usage;
//
// We can't dial an entry unless we
// know which one!
//
if (pszDllArg != NULL && pszFuncArg != NULL && pszEntryArg == NULL &&
!fStatusFlag)
{
goto usage;
}
if (fStatusFlag)
DumpStatus();
else {
//
// Convert to Unicode, if necessary.
//
#ifdef UNICODE
pszPhonebook = pszPhonebookArg;
pszEntry = pszEntryArg;
pszDll = pszDllArg;
pszFunc = pszFuncArg;
pszAddress = pszAddressArg;
#else
pszPhonebook = ConvertToAnsiString(pszPhonebookArg);
pszEntry = ConvertToAnsiString(pszEntryArg);
pszDll = ConvertToAnsiString(pszDllArg);
pszFunc = ConvertToAnsiString(pszFuncArg);
pszAddress = ConvertToAnsiString(pszAddressArg);
#endif
// XP 394237
//
// Supress the autodial prompt if a redial-on-link-failure
// prompt is already active
//
if ((fRedialFlag) || (fQuiet) || (!OtherRasautouActive()))
{
//
// Call the appropriate DLL entrypoint.
//
if ((pszDll == NULL && pszFunc == NULL) || fRedialFlag)
{
dwErr = DisplayRasDialog(
pszPhonebook,
pszEntry,
pszAddress,
fRedialFlag,
fQuiet);
}
else
{
dwErr = DisplayCustomDialog(
pszDll,
pszFunc,
pszPhonebook,
pszEntry,
pszAddress);
}
}
#ifndef UNICODE
FreeConvertedString(pszPhonebook);
FreeConvertedString(pszEntry);
FreeConvertedString(pszDll);
FreeConvertedString(pszFunc);
FreeConvertedString(pszAddress);
#endif
}
//
// Whistler bug 293751 rasphone.exe / rasautou.exe need to be "Fusionized"
// for UI conistency w/Connections Folder
//
if (g_hModule)
{
SHFusionUninitialize();
}
//
// Return status.
//
exit(dwErr);
}