496 lines
12 KiB
C++
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");
|
||
|
}
|
||
|
|