/* Copyright (c) 1994, Microsoft Corporation, all rights reserved ** ** rasapi16.c ** Remote Access external APIs ** Windows NT WOW 16->32 thunks, 16-bit side ** ** 04/02/94 Steve Cobb ** ** This is Win16 code and all included headers are Win16 headers. By it's ** nature, this code is sensitive to changes in either the Win16 or Win32 ** versions of RAS.H and the system definitions used therein. Numerous name ** conflicts make it unfeasible to include the Win32 headers here. Win32 ** definitions needed for mapping are defined locally with a "Win32:
" ** comment indicating the location of the duplicated Win32 definition. */ #include #include #include #include //#define BREAKONENTRY LPVOID AlignedAlloc( HGLOBAL FAR* ph, DWORD cb ); VOID AlignedFree( HGLOBAL h ); DWORD MapErrorCode( DWORD dwError ); /*--------------------------------------------------------------------------- ** Win32 definitions **--------------------------------------------------------------------------- */ /* The Win32 RAS structures are packed on 4-byte boundaries. */ #pragma pack(4) /* Win32: ras.h - RASCONNA ** Pads to different size. */ #define RASCONNA struct tagRASCONNA RASCONNA { DWORD dwSize; HRASCONN hrasconn; CHAR szEntryName[ RAS_MaxEntryName + 1 ]; }; #define LPRASCONNA RASCONNA FAR* /* Win32: ras.h - RASCONNSTATUSA ** The size of the RASCONNSTATE enum is different. ** Pads to different size. */ #define RASCONNSTATUSA struct tagRASCONNSTATUSA RASCONNSTATUSA { DWORD dwSize; DWORD rasconnstate; DWORD dwError; CHAR szDeviceType[ RAS_MaxDeviceType + 1 ]; CHAR szDeviceName[ RAS_MaxDeviceName + 1 ]; }; #define LPRASCONNSTATUSA RASCONNSTATUSA FAR* /* Win32: lmcons.h - UNLEN, PWLEN, and DNLEN */ #define NTUNLEN 256 #define NTPWLEN 256 #define NTDNLEN 15 /* Win32: ras.h - RASDIALPARAMSA ** The credential constants are different. */ #define RASDIALPARAMSA struct tagRASDIALPARAMSA RASDIALPARAMSA { DWORD dwSize; CHAR szEntryName[ RAS_MaxEntryName + 1 ]; CHAR szPhoneNumber[ RAS_MaxPhoneNumber + 1 ]; CHAR szCallbackNumber[ RAS_MaxCallbackNumber + 1 ]; CHAR szUserName[ NTUNLEN + 1 ]; CHAR szPassword[ NTPWLEN + 1 ]; CHAR szDomain[ NTDNLEN + 1 ]; }; #define LPRASDIALPARAMSA RASDIALPARAMSA FAR* /* Win32: ras.h - RASENTRYNAMEA ** Pads to different size. */ #define RASENTRYNAMEA struct tagRASENTRYNAMEA RASENTRYNAMEA { DWORD dwSize; CHAR szEntryName[ RAS_MaxEntryName + 1 ]; }; #define LPRASENTRYNAMEA RASENTRYNAMEA FAR* #pragma pack() /* Win32: \extapi\src\wow.c - RASAPI32.DLL WOW entry point prototypes */ typedef DWORD (FAR PASCAL* RASDIALWOW)( LPSTR, LPRASDIALPARAMS, DWORD, LPRASCONN ); typedef DWORD (FAR PASCAL* RASENUMCONNECTIONSWOW)( LPRASCONN, LPDWORD, LPDWORD ); typedef DWORD (FAR PASCAL* RASENUMENTRIESWOW)( LPSTR, LPSTR, LPRASENTRYNAME, LPDWORD, LPDWORD ); typedef DWORD (FAR PASCAL* RASGETCONNECTSTATUSWOW)( HRASCONN, LPRASCONNSTATUS ); typedef DWORD (FAR PASCAL* RASGETERRORSTRINGWOW)( DWORD, LPSTR, DWORD ); typedef DWORD (FAR PASCAL* RASHANGUPWOW)( HRASCONN ); /*--------------------------------------------------------------------------- ** Globals **--------------------------------------------------------------------------- */ /* The handle of the RASAPI32.DLL module returned by LoadLibraryEx32W. */ DWORD HRasApi32Dll = NULL; /* The unique RasDial notification message as registered in the system at ** startup (WM_RASDIALEVENT is just a default). */ UINT UnRasDialEventMsg = WM_RASDIALEVENT; /*--------------------------------------------------------------------------- ** Standard DLL entry points **--------------------------------------------------------------------------- */ int FAR PASCAL LibMain( HINSTANCE hInst, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine ) /* Standard DLL startup routine. */ { #ifdef BREAKONENTRY { _asm int 3 } #endif /* Don't even load on anything but NT WOW. */ if (!(GetWinFlags() & WF_WINNT)) return FALSE; /* Load the Win32 RAS API DLL. */ HRasApi32Dll = LoadLibraryEx32W( "RASAPI32.DLL", NULL, 0 ); if (!HRasApi32Dll) return FALSE; /* Register a unique message for RasDial notifications. */ { UINT unMsg = RegisterWindowMessage( RASDIALEVENT ); if (unMsg > 0) UnRasDialEventMsg = unMsg; } return TRUE; } int FAR PASCAL WEP( int nExitType ) /* Standard DLL exit routine. */ { #ifdef BREAKONENTRY { _asm int 3 } #endif if (HRasApi32Dll) FreeLibrary32W( HRasApi32Dll ); return TRUE; } /*--------------------------------------------------------------------------- ** 16->32 thunks **--------------------------------------------------------------------------- */ DWORD APIENTRY RasDial( LPSTR reserved, LPSTR lpszPhonebookPath, LPRASDIALPARAMS lprasdialparams, LPVOID reserved2, HWND hwndNotify, LPHRASCONN lphrasconn ) { DWORD dwErr; RASDIALWOW proc; LPRASDIALPARAMSA prdpa; HGLOBAL hrdpa; LPHRASCONN phrc; HGLOBAL hhrc; #ifdef BREAKONENTRY { _asm int 3 } #endif proc = (RASDIALWOW )GetProcAddress32W( HRasApi32Dll, "RasDialWow" ); if (!proc) return ERROR_INVALID_FUNCTION; (void )reserved; (void )reserved2; /* Account for the increased user name and password field lengths on NT. */ if (!(prdpa = (LPRASDIALPARAMSA )AlignedAlloc( &hrdpa, sizeof(RASDIALPARAMSA) ))) { return ERROR_NOT_ENOUGH_MEMORY; } prdpa->dwSize = sizeof(RASDIALPARAMSA); lstrcpy( prdpa->szEntryName, lprasdialparams->szEntryName ); lstrcpy( prdpa->szPhoneNumber, lprasdialparams->szPhoneNumber ); lstrcpy( prdpa->szCallbackNumber, lprasdialparams->szCallbackNumber ); lstrcpy( prdpa->szUserName, lprasdialparams->szUserName ); lstrcpy( prdpa->szPassword, lprasdialparams->szPassword ); lstrcpy( prdpa->szDomain, lprasdialparams->szDomain ); if (!(phrc = (LPHRASCONN )AlignedAlloc( &hhrc, sizeof(HRASCONN) ))) { AlignedFree( hrdpa ); return ERROR_NOT_ENOUGH_MEMORY; } *phrc = *lphrasconn; dwErr = CallProc32W( /* 16 */ (DWORD )lpszPhonebookPath, /* 8 */ (DWORD )prdpa, /* 4 */ (DWORD )hwndNotify | 0xFFFF0000, /* 2 */ (DWORD )UnRasDialEventMsg, /* 1 */ (DWORD )phrc, (LPVOID )proc, (DWORD )(16 + 8 + 1), (DWORD )5 ); *lphrasconn = *phrc; AlignedFree( hrdpa ); AlignedFree( hhrc ); return MapErrorCode( dwErr ); } DWORD APIENTRY RasEnumConnections( LPRASCONN lprasconn, LPDWORD lpcb, LPDWORD lpcConnections ) { DWORD dwErr; RASENUMCONNECTIONSWOW proc; LPRASCONNA prca; HGLOBAL hrca; LPDWORD pcb; HGLOBAL hcb; LPDWORD pcConnections; HGLOBAL hcConnections; #ifdef BREAKONENTRY { _asm int 3 } #endif proc = (RASENUMCONNECTIONSWOW )GetProcAddress32W( HRasApi32Dll, "RasEnumConnectionsWow" ); if (!proc) return ERROR_INVALID_FUNCTION; /* Check for bad sizes on this side before setting up a substitute buffer. */ if (!lprasconn || lprasconn->dwSize != sizeof(RASCONN)) return ERROR_INVALID_SIZE; if (!lpcb) return ERROR_INVALID_PARAMETER; if (!(pcb = (LPDWORD )AlignedAlloc( &hcb, sizeof(DWORD) ))) return ERROR_NOT_ENOUGH_MEMORY; *pcb = (*lpcb / sizeof(RASCONN)) * sizeof(RASCONNA); if (!(pcConnections = (LPDWORD )AlignedAlloc( &hcConnections, sizeof(DWORD) ))) { AlignedFree( hcb ); return ERROR_NOT_ENOUGH_MEMORY; } if (lpcConnections) *pcConnections = *lpcConnections; if (!(prca = (LPRASCONNA )AlignedAlloc( &hrca, *pcb ))) { AlignedFree( hcb ); AlignedFree( hcConnections ); return ERROR_NOT_ENOUGH_MEMORY; } prca->dwSize = sizeof(RASCONNA); dwErr = CallProc32W( /* 4 */ (DWORD )prca, /* 2 */ (DWORD )pcb, /* 1 */ (DWORD )pcConnections, (LPVOID )proc, (DWORD )(4 + 2 + 1), (DWORD )3 ); /* Copy result from substitute buffer back to caller's buffer. */ *lpcb = (*pcb / sizeof(RASCONNA)) * sizeof(RASCONN); if (lpcConnections) *lpcConnections = *pcConnections; if (MapErrorCode( dwErr ) != ERROR_BUFFER_TOO_SMALL) { DWORD i; LPRASCONNA lprcaSub = prca; LPRASCONN lprcCaller = lprasconn; for (i = 0; i < *pcConnections; ++i) { lprcCaller->dwSize = sizeof(RASCONN); lprcCaller->hrasconn = lprcaSub->hrasconn; lstrcpy( lprcCaller->szEntryName, lprcaSub->szEntryName ); ++lprcaSub; ++lprcCaller; } } AlignedFree( hcb ); AlignedFree( hcConnections ); AlignedFree( hrca ); return MapErrorCode( dwErr ); } DWORD APIENTRY RasEnumEntries( LPSTR reserved, LPSTR lpszPhonebookPath, LPRASENTRYNAME lprasentryname, LPDWORD lpcb, LPDWORD lpcEntries ) { DWORD dwErr; RASENUMENTRIESWOW proc; LPRASENTRYNAMEA prena; HGLOBAL hrena; LPDWORD pcb; HGLOBAL hcb; LPDWORD pcEntries; HGLOBAL hcEntries; #ifdef BREAKONENTRY { _asm int 3 } #endif proc = (RASENUMENTRIESWOW )GetProcAddress32W( HRasApi32Dll, "RasEnumEntriesWow" ); if (!proc) return ERROR_INVALID_FUNCTION; /* Check for bad sizes on this side before setting up a substitute buffer. */ if (!lprasentryname || lprasentryname->dwSize != sizeof(RASENTRYNAME)) return ERROR_INVALID_SIZE; if (!lpcb) return ERROR_INVALID_PARAMETER; if (!(pcb = (LPDWORD )AlignedAlloc( &hcb, sizeof(DWORD) ))) return ERROR_NOT_ENOUGH_MEMORY; *pcb = (*lpcb / sizeof(RASENTRYNAME)) * sizeof(RASENTRYNAMEA); if (!(pcEntries = (LPDWORD )AlignedAlloc( &hcEntries, sizeof(DWORD) ))) { AlignedFree( hcb ); return ERROR_NOT_ENOUGH_MEMORY; } if (lpcEntries) *pcEntries = *lpcEntries; if (!(prena = (LPRASENTRYNAMEA )AlignedAlloc( &hrena, *pcb ))) { AlignedFree( hcb ); AlignedFree( hcEntries ); return ERROR_NOT_ENOUGH_MEMORY; } prena->dwSize = sizeof(RASENTRYNAMEA); dwErr = CallProc32W( /* 16 */ (DWORD )reserved, /* 8 */ (DWORD )lpszPhonebookPath, /* 4 */ (DWORD )prena, /* 2 */ (DWORD )pcb, /* 1 */ (DWORD )pcEntries, (LPVOID )proc, (DWORD )(16 + 8 + 4 + 2 + 1), (DWORD ) 5 ); /* Copy result from substitute buffer back to caller's buffer. */ *lpcb = (*pcb / sizeof(RASENTRYNAMEA)) * sizeof(RASENTRYNAME); if (lpcEntries) *lpcEntries = *pcEntries; if (MapErrorCode( dwErr ) != ERROR_BUFFER_TOO_SMALL) { DWORD i; LPRASENTRYNAMEA lprenaSub = prena; LPRASENTRYNAME lprenCaller = lprasentryname; for (i = 0; i < *pcEntries; ++i) { lprenCaller->dwSize = sizeof(RASENTRYNAME); lstrcpy( lprenCaller->szEntryName, lprenaSub->szEntryName ); ++lprenaSub; ++lprenCaller; } } AlignedFree( hcb ); AlignedFree( hcEntries ); AlignedFree( hrena ); return MapErrorCode( dwErr ); } DWORD APIENTRY RasGetConnectStatus( HRASCONN hrasconn, LPRASCONNSTATUS lprasconnstatus ) { DWORD dwErr; RASGETCONNECTSTATUSWOW proc; LPRASCONNSTATUSA prcsa; HGLOBAL hrcsa; #ifdef BREAKONENTRY { _asm int 3 } #endif proc = (RASGETCONNECTSTATUSWOW )GetProcAddress32W( HRasApi32Dll, "RasGetConnectStatusWow" ); if (!proc) return ERROR_INVALID_FUNCTION; /* Check for bad size on this side before setting up a substitute buffer. */ if (!lprasconnstatus || lprasconnstatus->dwSize != sizeof(RASCONNSTATUS)) return ERROR_INVALID_SIZE; if (!(prcsa = (LPRASCONNSTATUSA )AlignedAlloc( &hrcsa, sizeof(RASCONNSTATUSA) ))) { return ERROR_NOT_ENOUGH_MEMORY; } prcsa->dwSize = sizeof(RASCONNSTATUSA); dwErr = CallProc32W( /* 2 */ (DWORD )hrasconn, /* 1 */ (DWORD )prcsa, (LPVOID )proc, (DWORD )1, (DWORD )2 ); /* Copy result from substitute buffer back to caller's buffer. */ lprasconnstatus->rasconnstate = (RASCONNSTATE )prcsa->rasconnstate; lprasconnstatus->dwError = prcsa->dwError; lstrcpy( lprasconnstatus->szDeviceType, prcsa->szDeviceType ); lstrcpy( lprasconnstatus->szDeviceName, prcsa->szDeviceName ); AlignedFree( hrcsa ); return MapErrorCode( dwErr ); } DWORD APIENTRY RasGetErrorString( UINT uErrorCode, LPSTR lpszBuf, DWORD cbBuf ) { DWORD dwErr; RASGETERRORSTRINGWOW proc; #ifdef BREAKONENTRY { _asm int 3 } #endif proc = (RASGETERRORSTRINGWOW )GetProcAddress32W( HRasApi32Dll, "RasGetErrorStringWow" ); if (!proc) return ERROR_INVALID_FUNCTION; dwErr = CallProc32W( /* 4 */ (DWORD )uErrorCode, /* 2 */ (DWORD )lpszBuf, /* 1 */ (DWORD )cbBuf, (LPVOID )proc, (DWORD )2, (DWORD )3 ); return MapErrorCode( dwErr ); } DWORD APIENTRY RasHangUp( HRASCONN hrasconn ) { DWORD dwErr; RASHANGUPWOW proc; #ifdef BREAKONENTRY { _asm int 3 } #endif proc = (RASHANGUPWOW )GetProcAddress32W( HRasApi32Dll, "RasHangUpWow" ); if (!proc) return ERROR_INVALID_FUNCTION; dwErr = CallProc32W( /* 1 */ (DWORD )hrasconn, (LPVOID )proc, (DWORD )0, (DWORD )1 ); return MapErrorCode( dwErr ); } /*--------------------------------------------------------------------------- ** Utilities **--------------------------------------------------------------------------- */ LPVOID AlignedAlloc( HGLOBAL FAR* ph, DWORD cb ) /* Returns address of block of 'cb' bytes aligned suitably for all ** platforms, or NULL if out of memory. If successful, callers '*ph' is ** set to the handle of the block, used with AllignedFree. */ { LPVOID pv = NULL; *ph = NULL; if (!(*ph = GlobalAlloc( GPTR, cb ))) return NULL; if (!(pv = (LPVOID )GlobalLock( *ph ))) { GlobalFree( *ph ); *ph = NULL; } return pv; } VOID AlignedFree( HGLOBAL h ) /* Frees a block allocated with AlignedAlloc identified by the 'h' ** returned from same. */ { if (h) { GlobalUnlock( h ); GlobalFree( h ); } } DWORD MapErrorCode( DWORD dwError ) /* Map Win32 error codes to Win16. (Win32: raserror.h) */ { /* These codes map, but the codes are different in Win16 and Win32. ** ERROR_NO_ISDN_CHANNELS_AVAILABLE truncated to 31 characters. See ** raserror.h. */ switch (dwError) { case 709: return ERROR_CHANGING_PASSWORD; case 710: return ERROR_OVERRUN; case 713: return ERROR_NO_ACTIVE_ISDN_LINES; case 714: return ERROR_NO_ISDN_CHANNELS_AVAILABL; } /* Pass everything else thru including codes that don't match up to ** anything on Win16 (e.g. RAS errors outside the 600 to 706 range). ** Reasoning is that an unmapped code is more valuable that some generic ** error like ERROR_UNKNOWN. */ return dwError; }