windows-nt/Source/XPSP1/NT/base/mvdm/wow16/user/net.c
2020-09-26 16:20:57 +08:00

562 lines
13 KiB
C

#include "user.h"
#include "winnet.h"
#include "netdlg.h"
void FAR PASCAL WriteOutProfiles(void);
#define IFNRESTORECONNECTION 23
#define IERR_MustBeLoggedOnToConnect 5000
#define CFNNETDRIVER 22 /* number of winnet entrypoints */
#define CFNNETDRIVER2 35 /* ... in Windows 3.1 */
extern FARPROC NEAR* pNetInfo; /* pointer to list of WINNET entrypoints */
extern HANDLE hWinnetDriver;
extern void FAR PASCAL WNetEnable( void );
extern WORD FAR PASCAL WNetGetCaps2(WORD nIndex); /* winnet.asm */
typedef struct _conntext
{
char szDevice[5];
char szPath[64];
char szPassword[32];
} CONNTEXT;
char CODESEG szNet[] = "Network";
char CODESEG szDialogs[] = "DefaultDialogs";
HWND hwndTopNet = NULL;
CONNTEXT FAR * lpctDlg;
#ifdef WOW
typedef VOID (FAR *LPTELLKRNL) (HINSTANCE);
#endif
WORD API IWNetGetCaps(WORD nIndex)
{
WORD wRet;
if (nIndex == 0xFFFF)
wRet = (WORD)hWinnetDriver;
else {
wRet = WNetGetCaps2(nIndex);
if (nIndex == WNNC_DIALOG) {
// turn off the drivers built in dialogs if
// win.ini [network] defaultdialogs=1
if (GetProfileInt(szNet, szDialogs, 0)) {
wRet &= ~(WNNC_DLG_ConnectDialog |
WNNC_DLG_DisconnectDialog |
WNNC_DLG_ConnectionDialog);
}
}
}
return wRet;
}
WORD API WNetErrorText(WORD wError,LPSTR lpsz, WORD cbMax)
{
WORD wInternalError;
WORD cb;
char szT[40];
if ((wError == WN_NET_ERROR)
&& (WNetGetError(&wInternalError) == WN_SUCCESS)
&& (WNetGetErrorText(wInternalError,lpsz,&cbMax) == WN_SUCCESS))
{
return cbMax;
}
else
{
cb = LoadString(hInstanceWin,STR_NETERRORS+wError,lpsz,cbMax);
if (!cb)
{
LoadString(hInstanceWin,STR_NETERRORS,szT,sizeof(szT));
cb = wvsprintf(lpsz, szT, (LPSTR)&wError);
}
}
return cb;
}
#if 0
/* CenterDialog() -
*
* Puts a dialog in an aesthetically pleasing place relative to its parent
*/
void near pascal CenterDialog(HWND hwnd)
{
int x, y;
/* center the dialog
*/
if (hwnd->hwndOwner)
{
x = hwnd->hwndOwner->rcWindow.left;
y = hwnd->hwndOwner->rcWindow.right;
x += rgwSysMet[SM_CXSIZE] + rgwSysMet[SM_CXFRAME];
y += rgwSysMet[SM_CYSIZE] + rgwSysMet[SM_CYFRAME];
}
else
{
x = (hwndDesktop->rcWindow.right
- (hwnd->rcWindow.right-hwnd->rcWindow.left)) / 2;
y = (hwndDesktop->rcWindow.bottom
- (hwnd->rcWindow.bottom-hwnd->rcWindow.top)) / 2;
}
SetWindowPos(hwnd,NULL,x,y,0,0,SWP_NOSIZE);
}
#endif
/* stub dlg proc for status dialog
*/
BOOL CALLBACK ProgressDlgProc(HWND hwnd, WORD wMsg, WPARAM wParam, LPARAM lParam)
{
switch (wMsg)
{
case WM_INITDIALOG:
// CenterDialog(hwnd);
break;
default:
return FALSE;
}
return TRUE;
}
/* PasswordDlgProc() -
*
* Get a password for a network resource
*/
BOOL CALLBACK PasswordDlgProc(HWND hwnd, WORD wMsg, WPARAM wParam, LPARAM lParam)
{
switch (wMsg)
{
case WM_INITDIALOG:
// CenterDialog(hwnd);
// Tell PenWin about this
if (lpRegisterPenAwareApp)
(*lpRegisterPenAwareApp)(1, TRUE);
// SetDlgItemText(hwnd,IDD_DEV,lpctDlg->szDevice);
SetDlgItemText(hwnd,IDD_PATH,lpctDlg->szPath);
SendDlgItemMessage(hwnd, IDD_PASS, EM_LIMITTEXT, (WPARAM)(sizeof(lpctDlg->szPassword)-1), 0L);
SetTimer(hwnd, 1, 30 * 1000, NULL);
break;
case WM_TIMER:
KillTimer(hwnd, 1);
wParam = (WPARAM)IDCANCEL;
goto TimeOut;
case WM_COMMAND:
switch ((WORD)wParam)
{
case IDD_PASS:
if (HIWORD(lParam) == EN_CHANGE)
KillTimer(hwnd, 1);
break;
case IDOK:
GetDlgItemText(hwnd,IDD_PASS,lpctDlg->szPassword, sizeof(lpctDlg->szPassword));
/*** FALL THRU ***/
case IDCANCEL:
case IDABORT:
TimeOut:
if (lpRegisterPenAwareApp)
(*lpRegisterPenAwareApp)(1, FALSE);
EndDialog(hwnd, (int)wParam);
break;
}
break;
default:
return FALSE;
}
return TRUE;
}
/* RestoreDevice() -
*
* Restores a single device. If fStartup is true, a dialog box is
* posted to list the connections being made (this posting is deferred
* until here so that if no permanant connections exist, none are
* restored.
*/
WORD NEAR PASCAL RestoreDevice(HWND hwndParent, LPSTR lpDev, BOOL fStartup, CONNTEXT FAR *lpct)
{
WORD wT;
WORD err;
WORD errorMode;
WORD result;
errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
result = WN_BAD_VALUE;
if (lstrlen(lpDev) > 4)
goto Done;
lstrcpy(lpct->szDevice,lpDev);
// If it's a drive that already exists then don't try to connect
// over it.
if (fStartup && *(lpDev+1) == ':') {
if (GetDriveType(*lpDev-'A')) {
// Drive already exists - don't stomp on it.
result = WN_CANCEL; // Don't report error.
goto Done;
}
}
if (fStartup)
goto GetFromINI;
wT = sizeof(lpct->szPath);
err = WNetGetConnection(lpct->szDevice,lpct->szPath,&wT);
if (err == WN_SUCCESS) {
result = WN_SUCCESS;
goto Done;
}
if (err == WN_DEVICE_ERROR) {
err = WNetCancelConnection(lpct->szDevice,FALSE);
if (err == WN_OPEN_FILES) {
// report a warning error to the user
WNetCancelConnection(lpct->szDevice,TRUE);
} else if (err != WN_SUCCESS) {
result = err;
goto Done;
}
} else if (err == WN_NOT_CONNECTED) {
GetFromINI:
if (!GetProfileString(szNet,lpct->szDevice,"",lpct->szPath,sizeof(lpct->szPath))) {
result = WN_NOT_CONNECTED;
goto Done;
}
} else if (err != WN_CONNECTION_CLOSED) {
result = err;
goto Done;
}
// initially attempt with a blank password
//
lpct->szPassword[0] = 0;
// if on startup, show the status dialog
//
if (fStartup) {
if (!hwndTopNet) {
hwndTopNet = CreateDialog(hInstanceWin,IDD_CONNECTPROGRESS,NULL,ProgressDlgProc);
if (!hwndTopNet)
goto TryConnection;
ShowWindow(hwndTopNet,SW_SHOW);
}
SetDlgItemText(hwndTopNet,IDD_DEV,lpct->szDevice);
SetDlgItemText(hwndTopNet,IDD_PATH,lpct->szPath);
UpdateWindow(hwndTopNet);
hwndParent = hwndTopNet;
}
TryConnection:
// lpct->szPath now contains the path
// and lpct->szPassword the password...
err = WNetAddConnection(lpct->szPath,lpct->szPassword,lpct->szDevice);
// if we're booting and the thing is connected, ignore
if (fStartup && err == WN_ALREADY_CONNECTED) {
result = WN_SUCCESS;
goto Done;
}
// if it was success or some other error, return
if (err != WN_BAD_PASSWORD && err != WN_ACCESS_DENIED) {
result = err;
goto Done;
}
// it was bad password. prompt the user for the correct password
lpctDlg = lpct;
switch (DialogBox(hInstanceWin,IDD_PASSWORD,hwndParent,PasswordDlgProc)) {
case -1:
result = WN_OUT_OF_MEMORY;
break;
case IDOK:
goto TryConnection;
break;
case IDCANCEL:
result = WN_CANCEL;
break;
case IDABORT:
result = WN_NET_ERROR;
break;
}
Done:
SetErrorMode(errorMode);
return result;
}
/* ReportError() -
*
* Tell the user why the network connection failed
*/
void NEAR PASCAL ReportError(HWND hwndParent, WORD err, CONNTEXT FAR *lpct)
{
char szTitle[80];
char szT[200];
char szError[150];
LPSTR rglp[2];
switch (err)
{
case WN_SUCCESS:
case WN_CANCEL:
case WN_NOT_CONNECTED:
return;
}
WNetErrorText(err,szT,sizeof(szT));
LoadString(hInstanceWin,STR_NETCONNMSG,szTitle,sizeof(szTitle));
rglp[0] = (LPSTR)lpct->szPath;
rglp[1] = (LPSTR)szT;
wvsprintf(szError,szTitle,(LPSTR)rglp);
LoadString(hInstanceWin,STR_NETCONNTTL,szTitle,sizeof(szTitle));
MessageBox(hwndParent,szError,szTitle,MB_OK|MB_ICONEXCLAMATION);
}
/* WNetRestoreConnection() -
*
* This function implements the "standard" restore-connection process.
* If the function is supported by the network driver, the driver is
* called instead. Otherwise, standard behaviour is supplied.
*/
typedef WORD (FAR PASCAL* PFN_NETRESTORECON)(HWND, LPSTR);
UINT API WNetRestoreConnection(HWND hwndParent, LPSTR lpszDevice)
{
static char CODESEG szInRestore[]="InRestoreNetConnect";
static char CODESEG szRestore[]="Restore";
char szDevice[10];
char szTitle[50];
char szMsg[255];
CONNTEXT ct;
WORD i;
WORD err;
BOOL bLoggedIn;
if (!pNetInfo)
return(WN_NOT_SUPPORTED);
if (WNetGetCaps(WNNC_CONNECTION) & WNNC_CON_RestoreConnection)
{
/* The device driver supports this call
*/
return (*(PFN_NETRESTORECON)(pNetInfo[IFNRESTORECONNECTION - 1]))(hwndParent, lpszDevice);
}
/* the network does not support restore connections. do the default
*/
if (HIWORD(lpszDevice))
return RestoreDevice(hwndParent,lpszDevice,FALSE,&ct);
// check to see if restoring net connects is enabled
if (!GetProfileInt(szNet,szRestore,1))
return(WN_SUCCESS);
/* Check if we previously aborted in the middle of restoring net
* connections.
*/
if (GetProfileInt(szNet,szInRestore,0))
{
/* We died in the middle of restoring net connects. Inform user.
*/
LoadString(hInstanceWin, STR_NETCRASHEDTITLE, szTitle, sizeof(szTitle));
LoadString(hInstanceWin, STR_NETCRASHEDMSG, szMsg, sizeof(szMsg));
err = MessageBox(NULL, szMsg, szTitle,
MB_ICONEXCLAMATION | MB_RETRYCANCEL | MB_SYSTEMMODAL);
if (err == IDCANCEL)
goto ExitRestoreNet;
}
WriteProfileString(szNet,szInRestore,"1");
/* Flush cache.
*/
WriteOutProfiles();
szDevice[1]=':';
szDevice[2]=0;
bLoggedIn = TRUE;
for (i = 0; i < 26; i++)
{
szDevice[0] = (char)('A' + i);
err = GetDriveType(i);
if (err == DRIVE_FIXED || err == DRIVE_REMOVABLE)
{
/* Don't restore to system drives in case the user added a ram
* drive or new hard disk or something...
*/
continue;
}
else
{
err = RestoreDevice(hwndParent,szDevice,TRUE,&ct);
}
hwndParent = hwndTopNet;
if ( (err == WN_NET_ERROR) &&
(WNetGetCaps (WNNC_NET_TYPE) == WNNC_NET_LanMan) &&
(WNetGetError (&err) == WN_SUCCESS) &&
(err == IERR_MustBeLoggedOnToConnect) )
{
bLoggedIn = FALSE;
break; /* if not logged on to LanMan, skip rest #8361 RAID */
}
else
// report error to user
ReportError(hwndParent,err,&ct);
}
/* Try to restore printer connections only if logged in. Fix for #8361
* [lalithar] - 11/14/91
*/
if (bLoggedIn)
{
szDevice[0] = 'L';
szDevice[1] = 'P';
szDevice[2] = 'T';
szDevice[4] = 0;
for (i = 0; i < 3; i++)
{
szDevice[3] = (char)('1' + i);
err = RestoreDevice(hwndParent,szDevice,TRUE,&ct);
hwndParent = hwndTopNet;
ReportError(hwndParent,err,&ct);
}
}
if (hwndTopNet)
{
DestroyWindow(hwndTopNet);
hwndTopNet = NULL;
}
ExitRestoreNet:
/* Write out a 0 since we are no longer restoring net connections.
*/
WriteProfileString(szNet,szInRestore,NULL);
return(WN_SUCCESS);
}
/*--------------------------------------------------------------------------*/
/* */
/* LW_InitNetInfo() - */
/* */
/*--------------------------------------------------------------------------*/
void FAR PASCAL LW_InitNetInfo(void)
{
int i;
char szDriver[64];
char szFile[32];
char szSection[32];
#ifdef WOW
HINSTANCE hInst;
LPTELLKRNL lpTellKrnlWhoNetDrvIs;
#endif
pNetInfo=NULL;
if (!LoadString(hInstanceWin,STR_NETDRIVER,szDriver,sizeof(szDriver)))
return;
if (!LoadString(hInstanceWin,STR_BOOT,szSection,sizeof(szSection)))
return;
if (!LoadString(hInstanceWin,STR_SYSTEMINI,szFile,sizeof(szFile)))
return;
/* look for in the tag NETWORK.DRV, with that as the output and the
* default string...
*/
GetPrivateProfileString(szSection,szDriver,szDriver,szDriver,
sizeof(szDriver),szFile);
/* if entry present, but blank, punt
*/
if (!*szDriver)
return;
hWinnetDriver = LoadLibrary(szDriver);
if (hWinnetDriver < HINSTANCE_ERROR)
return;
pNetInfo = (FARPROC NEAR*)UserLocalAlloc(ST_STRING,LPTR,sizeof(FARPROC)*CFNNETDRIVER2);
if (!pNetInfo)
{
FreeLibrary(hWinnetDriver);
return;
}
for (i=0; i<CFNNETDRIVER; i++)
{
pNetInfo[i]=GetProcAddress(hWinnetDriver,MAKEINTRESOURCE(i+1));
}
if (WNetGetCaps(WNNC_SPEC_VERSION) >= 0x30D)
{
for (;i<CFNNETDRIVER2; i++)
{
pNetInfo[i]=GetProcAddress(hWinnetDriver,MAKEINTRESOURCE(i+1));
}
}
#ifdef WOW
// Sets up krnl robustness mechanism which allows us to prevent non-user.exe
// modules from freeing the net driver (ie. causing ref count=0). Otherwise
// the proc addresses stored in pNetInfo would become invalid. bug #393078
hInst = LoadLibrary("krnl386.exe");
// if this fails, we just fly without robustness -- the way we used to...
if(HINSTANCE_ERROR <= hInst) {
lpTellKrnlWhoNetDrvIs =
(LPTELLKRNL) GetProcAddress(hInst, MAKEINTRESOURCE(545));
if(lpTellKrnlWhoNetDrvIs) {
lpTellKrnlWhoNetDrvIs(hWinnetDriver);
}
}
FreeLibrary(hInst);
#endif
WNetEnable();
}