You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1392 lines
36 KiB
1392 lines
36 KiB
#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"
|
|
|
|
#include "rasuip.h"
|
|
|
|
//
|
|
// Whistler bug 293751 rasphone.exe / rasautou.exe need to be "Fusionized" for
|
|
// UI conistency w/Connections Folder
|
|
//
|
|
HANDLE g_hModule = NULL;
|
|
|
|
BOOL g_UninitializeRas = FALSE;
|
|
|
|
//
|
|
// 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 );
|
|
|
|
g_UninitializeRas = TRUE;
|
|
|
|
}
|
|
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 );
|
|
|
|
g_UninitializeRas = TRUE;
|
|
|
|
}
|
|
|
|
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, ¶ms, &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();
|
|
}
|
|
|
|
if(g_UninitializeRas)
|
|
{
|
|
DwRasUninitialize();
|
|
}
|
|
|
|
//
|
|
// Return status.
|
|
//
|
|
exit(dwErr);
|
|
}
|