windows-nt/Source/XPSP1/NT/shell/ext/hnw/nconn32/sharing.cpp
2020-09-26 16:20:57 +08:00

496 lines
12 KiB
C++

//
// Sharing.cpp
//
// Code to install, enable, disable, and bind File and Printer sharing
// for Microsoft networks (VSERVER).
//
// History:
//
// 2/02/1999 KenSh Created for JetNet
// 9/29/1999 KenSh Repurposed for Home Networking Wizard
//
#include "stdafx.h"
#include "NetConn.h"
#include "nconnwrap.h"
#include "Registry.h"
#include "TheApp.h"
#include "ParseInf.h"
#include "HookUI.h"
// Local functions
//
BOOL WINAPI FindValidSharingEnumKey(LPSTR pszBuf, int cchBuf);
// Check the registry to see if file/printer sharing is installed.
BOOL WINAPI IsSharingInstalled(BOOL bExhaustive)
{
if (!FindValidSharingEnumKey(NULL, 0))
return FALSE;
if (bExhaustive)
{
if (!CheckInfSectionInstallation("netservr.inf", "VSERVER.Install"))
return FALSE;
}
return TRUE;
}
BOOL WINAPI FindValidSharingEnumKey(LPSTR pszBuf, int cchBuf)
{
return FindValidNetEnumKey(SZ_CLASS_SERVICE, SZ_SERVICE_VSERVER, pszBuf, cchBuf);
}
// Enables file/printer sharing on local NICs, disables it on Internet connections
HRESULT WINAPI EnableProtocolSharingAppropriately(LPCTSTR pszProtocolDeviceID)
{
HRESULT hr = EnableDisableProtocolSharing(pszProtocolDeviceID, TRUE, FALSE);
HRESULT hr2 = EnableDisableProtocolSharing(pszProtocolDeviceID, FALSE, TRUE);
if (hr2 != NETCONN_SUCCESS)
hr = hr2;
return hr;
}
// Enables or disables file/printer sharing for either Dial-Up or non-Dial-Up connections,
// but not both.
HRESULT WINAPI EnableDisableProtocolSharing(LPCTSTR pszProtocolDeviceID, BOOL bEnable, BOOL bDialUp)
{
HRESULT hr = NETCONN_SUCCESS;
NETADAPTER* prgAdapters;
int cAdapters = EnumNetAdapters(&prgAdapters);
for (int iAdapter = 0; iAdapter < cAdapters; iAdapter++)
{
NETADAPTER* pAdapter = &prgAdapters[iAdapter];
BOOL bExternalNic = IsAdapterBroadband(pAdapter);
if (bDialUp)
{
if (!bExternalNic && pAdapter->bNetType != NETTYPE_DIALUP)
continue;
}
else
{
if (bExternalNic || pAdapter->bNetType == NETTYPE_DIALUP)
continue;
}
LPTSTR* prgBindings;
int cBindings = EnumMatchingNetBindings(pAdapter->szEnumKey, pszProtocolDeviceID, &prgBindings);
for (int iBinding = 0; iBinding < cBindings; iBinding++)
{
HRESULT hr2;
if (bEnable)
{
hr2 = EnableSharingOnNetBinding(prgBindings[iBinding]);
}
else
{
hr2 = DisableSharingOnNetBinding(prgBindings[iBinding]);
}
if (hr2 != NETCONN_SUCCESS)
hr = hr2;
}
NetConnFree(prgBindings);
}
NetConnFree(prgAdapters);
return hr;
}
// pszNetBinding is of the form "MSTCP\0000"
HRESULT WINAPI DisableSharingOnNetBinding(LPCSTR pszNetBinding)
{
HRESULT hr = NETCONN_SUCCESS;
CRegistry regBindings;
TCHAR szRegKey[MAX_PATH];
wsprintf(szRegKey, "Enum\\Network\\%s\\Bindings", pszNetBinding);
if (regBindings.OpenKey(HKEY_LOCAL_MACHINE, szRegKey, KEY_ALL_ACCESS))
{
for (DWORD iBinding = 0; ; )
{
CHAR szBinding[64];
DWORD cchBinding = _countof(szBinding);
if (ERROR_SUCCESS != RegEnumValue(regBindings.m_hKey, iBinding, szBinding, &cchBinding, NULL, NULL, NULL, NULL))
break;
CHAR chSave = szBinding[8];
szBinding[8] = '\0';
BOOL bSharing = !lstrcmpi(szBinding, "VSERVER\\");
szBinding[8] = chSave;
if (bSharing)
{
RemoveBindingFromParent(regBindings.m_hKey, szBinding);
hr = NETCONN_NEED_RESTART;
// Restart the enumeration, since we've changed the key
iBinding = 0;
continue;
}
else
{
// Note: Sharing may still be bound to the client (VREDIR), but we
// don't remove that binding because Network Control Panel doesn't.
// (Verified on Win98 gold.)
// HRESULT hr2 = DisableSharingOnNetBinding(szBinding);
// if (hr2 != NETCONN_SUCCESS)
// hr = hr2;
}
iBinding += 1; // advance to next binding
}
}
return hr;
}
// pszNetBinding is of the form "MSTCP\0000"
HRESULT WINAPI EnableSharingOnNetBinding(LPCSTR pszNetBinding)
{
HRESULT hr = NETCONN_SUCCESS;
BOOL bFoundSharing = FALSE;
CRegistry regBindings;
TCHAR szRegKey[MAX_PATH];
wsprintf(szRegKey, "Enum\\Network\\%s\\Bindings", pszNetBinding);
if (!regBindings.CreateKey(HKEY_LOCAL_MACHINE, szRegKey, KEY_ALL_ACCESS))
{
ASSERT(FALSE);
return NETCONN_UNKNOWN_ERROR;
}
DWORD iBinding = 0;
for (;;)
{
CHAR szBinding[64];
DWORD cchBinding = _countof(szBinding);
if (ERROR_SUCCESS != RegEnumValue(regBindings.m_hKey, iBinding, szBinding, &cchBinding, NULL, NULL, NULL, NULL))
break;
CHAR chSave = szBinding[8];
szBinding[8] = '\0';
BOOL bSharing = !lstrcmpi(szBinding, "VSERVER\\");
szBinding[8] = chSave;
chSave = szBinding[7];
szBinding[7] = '\0';
BOOL bClient = !lstrcmpi(szBinding, "VREDIR\\");
szBinding[7] = chSave;
if (bSharing)
{
if (!IsValidNetEnumKey(SZ_CLASS_SERVICE, SZ_SERVICE_VSERVER, szBinding + _lengthof("VSERVER\\")))
{
// Found a dead link to nonexistent Enum item; delete it and restart search
regBindings.DeleteValue(szBinding);
iBinding = 0;
continue;
}
else
{
bFoundSharing = TRUE;
}
}
else if (bClient)
{
HRESULT hr2 = EnableSharingOnNetBinding(szBinding);
if (hr2 != NETCONN_SUCCESS)
hr = hr2;
}
iBinding++;
}
if (!bFoundSharing)
{
CHAR szBinding[64];
HRESULT hr2 = CreateNewFilePrintSharing(szBinding, _countof(szBinding));
if (hr2 != NETCONN_SUCCESS)
hr = hr2;
if (SUCCEEDED(hr2))
{
regBindings.SetStringValue(szBinding, "");
hr = NETCONN_NEED_RESTART;
}
}
return hr;
}
HRESULT WINAPI EnableSharingAppropriately()
{
HRESULT hr = NETCONN_SUCCESS;
NETADAPTER* prgAdapters;
int cAdapters = EnumNetAdapters(&prgAdapters);
for (int iAdapter = 0; iAdapter < cAdapters; iAdapter++)
{
NETADAPTER* pAdapter = &prgAdapters[iAdapter];
// Walk through each protocol bound to the adapter
LPTSTR* prgBindings;
int cBindings = EnumNetBindings(pAdapter->szEnumKey, &prgBindings);
for (int iBinding = 0; iBinding < cBindings; iBinding++)
{
LPTSTR pszBinding = prgBindings[iBinding];
HRESULT hr2 = NETCONN_SUCCESS;
BOOL bExternalNic = IsAdapterBroadband(pAdapter);
// Disable file/printer sharing on:
// * Dial-Up Adapters
// * PPTP connections
// * NIC used by ICS to connect to the Internet
if (pAdapter->bNetType == NETTYPE_DIALUP ||
pAdapter->bNetType == NETTYPE_PPTP ||
bExternalNic)
{
hr2 = DisableSharingOnNetBinding(pszBinding);
}
// Enable file/printer sharing on:
// * Ethernet adapters
// * IRDA adapters
else if (pAdapter->bNetType == NETTYPE_LAN ||
pAdapter->bNetType == NETTYPE_IRDA)
{
hr2 = EnableSharingOnNetBinding(pszBinding);
}
if (hr2 != NETCONN_SUCCESS)
hr = hr2;
}
NetConnFree(prgBindings);
}
NetConnFree(prgAdapters);
return hr;
}
// InstallSharing (public)
//
// Installs VSERVER, a.k.a. File and Printer sharing for Microsoft networks.
// The standard progress UI is (mostly) suppressed, and instead the given
// callback function is called so a custom progress UI can be implemented.
//
// Returns a NETCONN_xxx result, defined in NetConn.h
//
// History:
//
// 4/09/1999 KenSh Created
// 4/22/1999 KenSh Remove file-sharing on Dial-Up connections
//
HRESULT WINAPI InstallSharing(HWND hwndParent, PROGRESS_CALLBACK pfnProgress, LPVOID pvProgressParam)
{
HRESULT hr = NETCONN_SUCCESS;
BOOL bInstall = FALSE;
// Remove any broken bindings
RemoveBrokenNetItems(SZ_CLASS_SERVICE, SZ_SERVICE_VSERVER);
if (IsSharingInstalled(FALSE))
{
// Sharing is set up in registry, but check for missing files
if (!CheckInfSectionInstallation("netservr.inf", "VSERVER.Install"))
{
if (InstallInfSection("netservr.inf", "VSERVER.Install", TRUE))
{
hr = NETCONN_NEED_RESTART;
}
}
}
else
{
BeginSuppressNetdiUI(hwndParent, pfnProgress, pvProgressParam);
DWORD dwResult = CallClassInstaller16(hwndParent, SZ_CLASS_SERVICE, SZ_SERVICE_VSERVER);
EndSuppressNetdiUI();
hr = HresultFromCCI(dwResult);
if (g_bUserAbort)
{
hr = NETCONN_USER_ABORT;
}
else if (SUCCEEDED(hr))
{
hr = NETCONN_NEED_RESTART;
}
// Total hack to work around JetNet bug 1193
// DoDummyDialog(hwndParent);
}
// if (SUCCEEDED(hr))
// {
// HRESULT hr2 = EnableSharingAppropriately();
// if (hr2 != NETCONN_SUCCESS)
// hr = hr2;
// }
HRESULT hr2 = EnableFileSharing();
if (hr2 != NETCONN_SUCCESS)
hr = hr2;
hr2 = EnablePrinterSharing();
if (hr2 != NETCONN_SUCCESS)
hr = hr2;
return hr;
}
// pConflict may be NULL if you don't need the details
BOOL WINAPI FindConflictingService(LPCSTR pszWantService, NETSERVICE* pConflict)
{
CRegistry reg;
if (reg.OpenKey(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\Class\\NetService", KEY_READ))
{
TCHAR szSubKey[80];
for (DWORD iService = 0; ; iService++)
{
DWORD cchSubKey = _countof(szSubKey);
if (ERROR_SUCCESS != RegEnumKeyEx(reg.m_hKey, iService, szSubKey, &cchSubKey, NULL, NULL, NULL, NULL))
break;
CRegistry regSubKey;
if (regSubKey.OpenKey(reg.m_hKey, szSubKey, KEY_READ))
{
CRegistry regNdi;
if (regNdi.OpenKey(regSubKey.m_hKey, "Ndi", KEY_READ))
{
CRegistry regCompat;
if (regCompat.OpenKey(regNdi.m_hKey, "Compatibility", KEY_READ))
{
CString strExclude;
if (regCompat.QueryStringValue("ExcludeAll", strExclude))
{
if (CheckMatchingInterface(pszWantService, strExclude))
{
if (pConflict != NULL)
{
regNdi.QueryStringValue("DeviceID", pConflict->szDeviceID, _countof(pConflict->szDeviceID));
regSubKey.QueryStringValue("DriverDesc", pConflict->szDisplayName, _countof(pConflict->szDisplayName));
wsprintf(pConflict->szClassKey, "NetService\\%s", szSubKey);
}
return TRUE;
}
}
}
}
}
}
}
return FALSE;
}
// pszBuf is filled with the new binding's enum key, e.g. "VSERVER\0001"
HRESULT CreateNewFilePrintSharing(LPSTR pszBuf, int cchBuf)
{
HRESULT hr;
if (FAILED(hr = FindAndCloneNetEnumKey(SZ_CLASS_SERVICE, SZ_SERVICE_VSERVER, pszBuf, cchBuf)))
{
ASSERT(FALSE);
return hr;
}
// Now pszBuf contains a string of the form "VSERVER\0001"
CHAR szBindings[60];
CRegistry regBindings;
lstrcpy(szBindings, pszBuf); // "VSERVER\0001"
lstrcat(szBindings, "\\Bindings"); // "VSERVER\0001\Bindings"
if (FAILED(hr = OpenNetEnumKey(regBindings, szBindings, KEY_ALL_ACCESS)))
{
ASSERT(FALSE);
return hr;
}
// Delete existing bindings (shouldn't be any, right?)
regBindings.DeleteAllValues();
return NETCONN_SUCCESS;
}
BOOL IsSharingEnabledHelper(LPCTSTR pszThis)
{
CRegistry reg;
if (reg.OpenKey(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\VxD\\VNETSUP", KEY_READ))
{
// If the value is missing or says "Yes", then sharing is enabled
char szBuf[10];
return (!reg.QueryStringValue(pszThis, szBuf, _countof(szBuf)) || 0 == lstrcmpi(szBuf, "Yes"));
}
return FALSE;
}
BOOL WINAPI IsFileSharingEnabled()
{
return IsSharingEnabledHelper("FileSharing");
}
BOOL WINAPI IsPrinterSharingEnabled()
{
return IsSharingEnabledHelper("PrintSharing");
}
HRESULT WINAPI EnableSharingHelper(LPCTSTR pszThis, LPCTSTR pszOther)
{
HRESULT hr = NETCONN_SUCCESS;
CRegistry reg;
if (reg.OpenKey(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\VxD\\VNETSUP"))
{
// If Printer sharing is "No", then set File sharing to "Yes".
// If Printer sharing is missing or is "Yes", delete both values (enables both).
char szBuf[10];
if (reg.QueryStringValue(pszOther, szBuf, _countof(szBuf)) &&
0 != lstrcmpi(szBuf, "Yes"))
{
// Set file sharing value to "Yes" (if it's not already set)
if (!reg.QueryStringValue(pszThis, szBuf, _countof(szBuf)) ||
0 != lstrcmpi(szBuf, "Yes"))
{
reg.SetStringValue(pszThis, "Yes");
hr = NETCONN_NEED_RESTART;
}
}
else
{
// Delete file-sharing and printer-sharing entries (enables both).
if (reg.QueryStringValue(pszThis, szBuf, _countof(szBuf)) &&
0 != lstrcmpi(szBuf, "Yes"))
{
reg.DeleteValue(pszThis);
reg.DeleteValue(pszOther);
hr = NETCONN_NEED_RESTART;
}
}
}
return hr;
}
HRESULT WINAPI EnableFileSharing()
{
return EnableSharingHelper("FileSharing", "PrintSharing");
}
HRESULT WINAPI EnablePrinterSharing()
{
return EnableSharingHelper("PrintSharing", "FileSharing");
}