// // 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"); }