438 lines
13 KiB
C
438 lines
13 KiB
C
|
/*
|
||
|
+-------------------------------------------------------------------------+
|
||
|
| Network Utility Functions |
|
||
|
+-------------------------------------------------------------------------+
|
||
|
| (c) Copyright 1993-1994 |
|
||
|
| Microsoft Corp. |
|
||
|
| All rights reserved |
|
||
|
| |
|
||
|
| Program : [NetUtil.c] |
|
||
|
| Programmer : Arthur Hanson |
|
||
|
| Original Program Date : [Feb 16, 1993] |
|
||
|
| Last Update : [Jun 16, 1994] |
|
||
|
| |
|
||
|
| Version: 1.00 |
|
||
|
| |
|
||
|
| Description: |
|
||
|
| |
|
||
|
| History: |
|
||
|
| arth Jun 16, 1994 1.00 Original Version. |
|
||
|
| |
|
||
|
+-------------------------------------------------------------------------+
|
||
|
*/
|
||
|
|
||
|
#include "globals.h"
|
||
|
#include "netutil.h"
|
||
|
|
||
|
static LPTSTR ServName;
|
||
|
static TCHAR szPassword[PWLEN+1];
|
||
|
static TCHAR szUserName[MAX_USER_NAME_LEN + 1];
|
||
|
|
||
|
LRESULT CALLBACK PasswordDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
|
||
|
BOOL BadPassword;
|
||
|
|
||
|
/*+-------------------------------------------------------------------------+
|
||
|
| FixPathSlash()
|
||
|
|
|
||
|
+-------------------------------------------------------------------------+*/
|
||
|
void FixPathSlash(LPTSTR NewPath, LPTSTR Path) {
|
||
|
UINT PathLen;
|
||
|
lstrcpy(NewPath, Path);
|
||
|
|
||
|
PathLen = lstrlen(Path);
|
||
|
// If ending character is not a slash then put one on
|
||
|
if (PathLen && (Path[PathLen - 1] != '\\'))
|
||
|
lstrcat(NewPath, TEXT("\\"));
|
||
|
|
||
|
} // FixPathSlash
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------+
|
||
|
| ShareNameParse()
|
||
|
|
|
||
|
+-------------------------------------------------------------------------+*/
|
||
|
LPTSTR ShareNameParse(LPTSTR ShareName) {
|
||
|
ULONG i;
|
||
|
|
||
|
i = lstrlen(ShareName);
|
||
|
if (!i)
|
||
|
return ShareName;
|
||
|
|
||
|
// Scan backwards for first slash
|
||
|
i--;
|
||
|
while (i && ShareName[i] != TEXT('\\'))
|
||
|
i--;
|
||
|
|
||
|
// if found slash then increment past it
|
||
|
if (i)
|
||
|
i++;
|
||
|
|
||
|
return &ShareName[i];
|
||
|
|
||
|
} // ShareNameParse
|
||
|
|
||
|
|
||
|
static LPTSTR LocName = NULL;
|
||
|
/*+-------------------------------------------------------------------------+
|
||
|
| GetLocalName()
|
||
|
|
|
||
|
+-------------------------------------------------------------------------+*/
|
||
|
void GetLocalName(LPTSTR *lpLocalName) {
|
||
|
int size;
|
||
|
|
||
|
if (LocName != NULL) {
|
||
|
*lpLocalName = LocName;
|
||
|
} else {
|
||
|
LocName = AllocMemory((MAX_COMPUTERNAME_LENGTH + 1) * sizeof(TCHAR));
|
||
|
size = MAX_COMPUTERNAME_LENGTH + 1;
|
||
|
|
||
|
if (LocName) {
|
||
|
GetComputerName(LocName, &size);
|
||
|
*lpLocalName = LocName;
|
||
|
} else
|
||
|
*lpLocalName = NULL;
|
||
|
}
|
||
|
|
||
|
} // GetLocalName
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------+
|
||
|
| SetProvider()
|
||
|
|
|
||
|
+-------------------------------------------------------------------------+*/
|
||
|
BOOL SetProvider(LPTSTR Provider, NETRESOURCE *ResourceBuf) {
|
||
|
ResourceBuf->dwScope = RESOURCE_GLOBALNET;
|
||
|
ResourceBuf->dwType = RESOURCETYPE_DISK;
|
||
|
ResourceBuf->dwDisplayType = RESOURCEDISPLAYTYPE_GENERIC;
|
||
|
|
||
|
// Don't take the frigging _RESERVED flag out - it isn't documented except in the include
|
||
|
// file and it crashes without it!
|
||
|
ResourceBuf->dwUsage = RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_RESERVED;
|
||
|
|
||
|
ResourceBuf->lpLocalName = NULL;
|
||
|
ResourceBuf->lpRemoteName = Provider;
|
||
|
ResourceBuf->lpComment = NULL;
|
||
|
ResourceBuf->lpProvider = Provider;
|
||
|
return TRUE;
|
||
|
|
||
|
} // SetProvider
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------+
|
||
|
| AllocEnumBuffer()
|
||
|
|
|
||
|
+-------------------------------------------------------------------------+*/
|
||
|
ENUM_REC *AllocEnumBuffer() {
|
||
|
ENUM_REC *Buf;
|
||
|
|
||
|
Buf = (ENUM_REC *) AllocMemory(sizeof(ENUM_REC));
|
||
|
|
||
|
if (Buf) {
|
||
|
// Init the record
|
||
|
Buf->next = NULL;
|
||
|
Buf->cEntries = 0;
|
||
|
Buf->cbBuffer = 0;
|
||
|
Buf->lpnr = NULL;
|
||
|
}
|
||
|
|
||
|
return Buf;
|
||
|
|
||
|
} // AllocEnumBuffer
|
||
|
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------+
|
||
|
| EnumBufferBuild()
|
||
|
|
|
||
|
| Uses WNetEnum to enumerate the resource. WNetEnum is really brain-
|
||
|
| dead so we need to create a temporary holding array and then build
|
||
|
| up a finalized complete buffer in the end. A linked list of inter-
|
||
|
| mediate buffer records is created first.
|
||
|
|
|
||
|
+-------------------------------------------------------------------------+*/
|
||
|
DWORD FAR PASCAL EnumBufferBuild(ENUM_REC **BufHead, int *NumBufs, NETRESOURCE ResourceBuf) {
|
||
|
DWORD status = ERROR_NO_NETWORK;
|
||
|
ENUM_REC *CurrBuf;
|
||
|
DWORD dwResultEnum;
|
||
|
HANDLE hEnum = NULL;
|
||
|
DWORD cbBuffer = 16384; // 16K default buffer size.
|
||
|
DWORD cEntries = 0xFFFFFFFF; // enumerate all possible entries
|
||
|
ENUM_REC **lppEnumRec;
|
||
|
LPNETRESOURCE lpnrLocal;
|
||
|
|
||
|
status = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &ResourceBuf, &hEnum);
|
||
|
|
||
|
if (status == NO_ERROR) {
|
||
|
|
||
|
*BufHead = NULL;
|
||
|
lppEnumRec = BufHead;
|
||
|
|
||
|
do {
|
||
|
|
||
|
cbBuffer = 16384; // 16K default buffer size
|
||
|
cEntries = 0xFFFFFFFF; // enumerate all possible entries
|
||
|
|
||
|
// Allocate memory for NETRESOURCE structures.
|
||
|
lpnrLocal = (LPNETRESOURCE) AllocMemory(cbBuffer);
|
||
|
|
||
|
if (lpnrLocal == NULL) {
|
||
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
dwResultEnum = WNetEnumResource(hEnum, &cEntries, (LPVOID) lpnrLocal, &cbBuffer);
|
||
|
|
||
|
if (dwResultEnum == NO_ERROR) {
|
||
|
// Create a new Enum rec and link it to the chain
|
||
|
*lppEnumRec = AllocEnumBuffer();
|
||
|
|
||
|
if (*lppEnumRec == NULL) {
|
||
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
CurrBuf = *lppEnumRec;
|
||
|
|
||
|
// Init for next loop through buffer
|
||
|
lppEnumRec = &CurrBuf->next;
|
||
|
|
||
|
// Put enumeration buffer in our Enum rec.
|
||
|
CurrBuf->lpnr = lpnrLocal;
|
||
|
CurrBuf->cEntries = cEntries;
|
||
|
CurrBuf->cbBuffer = cbBuffer;
|
||
|
(*NumBufs)++;
|
||
|
|
||
|
} else { // Since this is not assigned in a rec we need to free it here.
|
||
|
FreeMemory((HGLOBAL) lpnrLocal);
|
||
|
|
||
|
if (dwResultEnum != ERROR_NO_MORE_ITEMS) {
|
||
|
status = dwResultEnum;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} while (dwResultEnum != ERROR_NO_MORE_ITEMS);
|
||
|
|
||
|
status = WNetCloseEnum(hEnum);
|
||
|
|
||
|
}
|
||
|
|
||
|
return status;
|
||
|
|
||
|
} // EnumBufferBuild
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------+
|
||
|
| UseAddPswd()
|
||
|
|
|
||
|
| Attempts to make connections to \\szServer\admin$, asking for
|
||
|
| passwords if necessary.
|
||
|
|
|
||
|
| Returns TRUE if use was added,
|
||
|
| FALSE otherwise
|
||
|
|
|
||
|
+-------------------------------------------------------------------------+*/
|
||
|
BOOL UseAddPswd(HWND hwnd, LPTSTR UserName, LPTSTR lpszServer, LPTSTR lpszShare, LPTSTR Provider) {
|
||
|
WORD nState;
|
||
|
WORD fCancel;
|
||
|
DLGPROC lpProc;
|
||
|
NETRESOURCE nr;
|
||
|
NET_API_STATUS retcode;
|
||
|
LPTSTR lpPassword;
|
||
|
static TCHAR szTmp[MAX_UNC_PATH+1];
|
||
|
|
||
|
ServName = lpszServer;
|
||
|
|
||
|
nr.dwScope = 0;
|
||
|
nr.dwType = RESOURCETYPE_DISK;
|
||
|
nr.dwDisplayType = 0;
|
||
|
nr.dwUsage = 0;
|
||
|
nr.lpProvider = NULL;
|
||
|
|
||
|
nState = 1; // try default password
|
||
|
lpPassword = NULL;
|
||
|
BadPassword = FALSE;
|
||
|
lstrcpy(szUserName, UserName);
|
||
|
|
||
|
for(;;) {
|
||
|
// Concatenate server and share
|
||
|
wsprintf(szTmp, TEXT("%s\\%s"), lpszServer, lpszShare);
|
||
|
|
||
|
// Fill in data structure
|
||
|
nr.lpLocalName = NULL;
|
||
|
nr.lpRemoteName = szTmp;
|
||
|
nr.lpProvider = Provider;
|
||
|
|
||
|
// Try to make the connection
|
||
|
if (lstrlen(szUserName))
|
||
|
retcode = WNetAddConnection2(&nr, lpPassword, szUserName, 0);
|
||
|
else
|
||
|
retcode = WNetAddConnection2(&nr, lpPassword, NULL, 0);
|
||
|
|
||
|
switch(retcode) {
|
||
|
case NERR_Success:
|
||
|
lstrcpy(UserName, szUserName);
|
||
|
return TRUE;
|
||
|
|
||
|
case ERROR_INVALID_PASSWORD:
|
||
|
BadPassword = TRUE;
|
||
|
break;
|
||
|
|
||
|
case ERROR_ACCESS_DENIED:
|
||
|
case ERROR_NETWORK_ACCESS_DENIED:
|
||
|
case ERROR_SESSION_CREDENTIAL_CONFLICT:
|
||
|
case ERROR_NO_SUCH_USER:
|
||
|
case ERROR_NO_MORE_ITEMS:
|
||
|
case ERROR_LOGON_FAILURE:
|
||
|
BadPassword = FALSE;
|
||
|
break;
|
||
|
|
||
|
case ERROR_BAD_NETPATH:
|
||
|
case ERROR_BAD_NET_NAME:
|
||
|
|
||
|
default:
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Get new password from user
|
||
|
lpProc = MakeProcInstance(PasswordDlgProc, hInst);
|
||
|
fCancel = !DialogBoxParam(hInst, TEXT("PasswordEnter"), hwnd, lpProc, 0);
|
||
|
|
||
|
// Gamble call only once
|
||
|
FreeProcInstance(lpProc);
|
||
|
|
||
|
// Save...
|
||
|
if(!fCancel) {
|
||
|
if(nState) {
|
||
|
nState = 2; // try specified password
|
||
|
lpPassword = szPassword;
|
||
|
} else {
|
||
|
nState = 1; // try default password
|
||
|
lpPassword = NULL;
|
||
|
}
|
||
|
} else {
|
||
|
SetLastError(ERROR_SUCCESS); // just aborting...
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} // UseAddPswd
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------+
|
||
|
| PasswordDlgProc()
|
||
|
|
|
||
|
| Gets a password from the user and copies it into the string pointed
|
||
|
| to by lParam. This string must have room for at least (PWLEN + 1)
|
||
|
| characters. Returns TRUE if OK is pressed, or FALSE if Cancel
|
||
|
|
|
||
|
+-------------------------------------------------------------------------+*/
|
||
|
LRESULT CALLBACK PasswordDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
|
||
|
|
||
|
switch (msg) {
|
||
|
case WM_INITDIALOG:
|
||
|
CursorNormal();
|
||
|
|
||
|
// Center the dialog over the application window
|
||
|
CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
|
||
|
|
||
|
SetDlgItemText(hDlg, IDC_SERVNAME, ServName);
|
||
|
SendDlgItemMessage(hDlg, IDC_PASSWORD, EM_LIMITTEXT, PWLEN, 0L);
|
||
|
SendDlgItemMessage(hDlg, IDC_USERNAME, EM_LIMITTEXT, MAX_USER_NAME_LEN, 0L);
|
||
|
PostMessage(hDlg, WM_COMMAND, ID_INIT, 0L);
|
||
|
break;
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
switch(wParam) {
|
||
|
case IDOK:
|
||
|
CursorHourGlass();
|
||
|
GetDlgItemText(hDlg, IDC_PASSWORD, szPassword, PWLEN+1);
|
||
|
GetDlgItemText(hDlg, IDC_USERNAME, szUserName, MAX_USER_NAME_LEN+1);
|
||
|
|
||
|
EndDialog(hDlg, TRUE);
|
||
|
break;
|
||
|
|
||
|
case IDCANCEL:
|
||
|
CursorHourGlass();
|
||
|
EndDialog(hDlg, FALSE);
|
||
|
break;
|
||
|
|
||
|
case ID_INIT:
|
||
|
SendDlgItemMessage(hDlg, IDC_USERNAME, WM_SETTEXT, 0, (LPARAM) szUserName);
|
||
|
|
||
|
if (BadPassword)
|
||
|
SetFocus(GetDlgItem(hDlg, IDC_PASSWORD));
|
||
|
else {
|
||
|
SetFocus(GetDlgItem(hDlg, IDC_USERNAME));
|
||
|
SendDlgItemMessage(hDlg, IDC_USERNAME, EM_SETSEL, 0, (LPARAM) MAKELPARAM(0, -1) );
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return FALSE;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
|
||
|
} // PasswordDlgProc
|
||
|
|
||
|
|
||
|
/*+-------------------------------------------------------------------------+
|
||
|
| NicePath()
|
||
|
|
|
||
|
+-------------------------------------------------------------------------+*/
|
||
|
LPTSTR NicePath(int Len, LPTSTR Path) {
|
||
|
static TCHAR NewPath[MAX_PATH + 80];
|
||
|
int eptr, fptr;
|
||
|
|
||
|
// If the path fits then just return it
|
||
|
if (lstrlen(Path) <= Len) {
|
||
|
lstrcpy(NewPath, Path);
|
||
|
return NewPath;
|
||
|
}
|
||
|
|
||
|
// The path doesn't fit, so need to reduce it down in size - to do this first try
|
||
|
// to get the last part of the path looking for slash that starts it.
|
||
|
eptr = fptr = 0;
|
||
|
while (Path[eptr] != TEXT('\0'))
|
||
|
eptr++;
|
||
|
|
||
|
// back up before ending NULL also before any ending slash
|
||
|
eptr--;
|
||
|
while ((Path[eptr] == TEXT('\\')) && eptr > 0)
|
||
|
eptr--;
|
||
|
|
||
|
// now try to find beginning slash
|
||
|
while ((Path[eptr] != TEXT('\\')) && eptr > 0)
|
||
|
eptr--;
|
||
|
|
||
|
// if at beginning of string then is just one name so copy all of it we can
|
||
|
if (eptr == 0) {
|
||
|
lstrcpyn(NewPath, Path, Len);
|
||
|
return NewPath;
|
||
|
}
|
||
|
|
||
|
// check if the name after the last slash can all fit - also take into account
|
||
|
// the "..." we are going to tack into the name
|
||
|
fptr = lstrlen(Path) - eptr;
|
||
|
fptr += 4;
|
||
|
if (fptr >= Len) {
|
||
|
lstrcpyn(NewPath, &Path[eptr], Len);
|
||
|
return NewPath;
|
||
|
}
|
||
|
|
||
|
// We need to create a path shortening to the desired length by removing the mid
|
||
|
// part of the path and replacing it with "..."
|
||
|
fptr = Len - fptr;
|
||
|
lstrcpyn(NewPath, Path, fptr);
|
||
|
lstrcat(NewPath, TEXT("..."));
|
||
|
lstrcat(NewPath, &Path[eptr]);
|
||
|
return NewPath;
|
||
|
|
||
|
} // NicePath
|