// // TheApp.cpp // // 16-bit code to install network components such as TCP/IP. // // History: // // 2/02/1999 KenSh Created for JetNet, largely from Internet Connection Wizard // 9/29/1999 KenSh Adapterd for Home Networking Wizard // #include "stdafx.h" #include #include #include "NConn16.h" #include "strstri.h" extern "C" { // Define missing decs so it builds. typedef HKEY* LPHKEY; typedef const BYTE* LPCBYTE; #define WINCAPI // missing #include #include } #ifndef _countof #define _countof(ar) (sizeof(ar) / sizeof((ar)[0])) #endif extern "C" BOOL FAR PASCAL thk_ThunkConnect16(LPSTR pszDll16, LPSTR pszDll32, WORD hInst, DWORD dwReason); // // SetupX function prototypes // typedef RETERR (WINAPI PASCAL FAR * PROC_DiOpenDevRegKey)( LPDEVICE_INFO lpdi, LPHKEY lphk, int iFlags); typedef DWORD (WINAPI FAR * PROC_SURegSetValueEx)(HKEY hKey,LPCSTR lpszValueName, DWORD dwReserved, DWORD dwType, LPBYTE lpszValue, DWORD dwValSize); typedef RETERR (WINAPI FAR * PROC_DiCreateDeviceInfo)( LPLPDEVICE_INFO lplpdi, // Ptr to ptr to dev info LPCSTR lpszDescription, // If non-null then description string DWORD hDevnode, // BUGBUG -- MAKE A DEVNODE HKEY hkey, // Registry hkey for dev info LPCSTR lpszRegsubkey, // If non-null then reg subkey string LPCSTR lpszClassName, // If non-null then class name string HWND hwndParent); // If non-null then hwnd of parent typedef RETERR (WINAPI FAR * PROC_DiDestroyDeviceInfoList)(LPDEVICE_INFO lpdi); typedef RETERR (WINAPI FAR * PROC_DiCallClassInstaller)(DI_FUNCTION diFctn, LPDEVICE_INFO lpdi); typedef DWORD (WINAPI FAR * PROC_SURegCloseKey)(HKEY hKey); typedef RETERR (WINAPI FAR * PROC_DiGetClassDevs)( LPLPDEVICE_INFO lplpdi, // Ptr to ptr to dev info LPCSTR lpszClassName, // Must be name of class HWND hwndParent, // If non-null then hwnd of parent int iFlags); // Options typedef RETERR (WINAPI FAR * PROC_DiSelectDevice)( LPDEVICE_INFO lpdi ); typedef RETERR (WINAPI FAR * PROC_DiBuildCompatDrvList)(LPDEVICE_INFO lpdi); typedef RETERR (WINAPI FAR * PASCAL PROC_DiCreateDevRegKey)( LPDEVICE_INFO lpdi, LPHKEY lphk, HINF hinf, LPCSTR lpszInfSection, int iFlags); typedef RETERR (WINAPI FAR * PASCAL PROC_DiDeleteDevRegKey)(LPDEVICE_INFO lpdi, int iFlags); PROC_DiOpenDevRegKey _pfnDiOpenDevRegKey; PROC_SURegSetValueEx _pfnSURegSetValueEx; PROC_DiCreateDeviceInfo _pfnDiCreateDeviceInfo; PROC_DiDestroyDeviceInfoList _pfnDiDestroyDeviceInfoList; PROC_DiCallClassInstaller _pfnDiCallClassInstaller; PROC_SURegCloseKey _pfnSURegCloseKey; PROC_DiGetClassDevs _pfnDiGetClassDevs; PROC_DiSelectDevice _pfnDiSelectDevice; PROC_DiBuildCompatDrvList _pfnDiBuildCompatDrvList; PROC_DiCreateDevRegKey _pfnDiCreateDevRegKey; PROC_DiDeleteDevRegKey _pfnDiDeleteDevRegKey; int g_cSetupxInit = 0; HINSTANCE g_hInstSetupx = NULL; BOOL InitSetupx() { if (g_hInstSetupx == NULL) { g_hInstSetupx = LoadLibrary("setupx.dll"); if (g_hInstSetupx < (HINSTANCE)HINSTANCE_ERROR) return FALSE; _pfnDiOpenDevRegKey = (PROC_DiOpenDevRegKey)GetProcAddress(g_hInstSetupx, "DiOpenDevRegKey"); _pfnSURegSetValueEx = (PROC_SURegSetValueEx)GetProcAddress(g_hInstSetupx, "SURegSetValueEx"); _pfnDiCreateDeviceInfo = (PROC_DiCreateDeviceInfo)GetProcAddress(g_hInstSetupx, "DiCreateDeviceInfo"); _pfnDiDestroyDeviceInfoList = (PROC_DiDestroyDeviceInfoList)GetProcAddress(g_hInstSetupx, "DiDestroyDeviceInfoList"); _pfnDiCallClassInstaller = (PROC_DiCallClassInstaller)GetProcAddress(g_hInstSetupx, "DiCallClassInstaller"); _pfnSURegCloseKey = (PROC_SURegCloseKey)GetProcAddress(g_hInstSetupx, "SURegCloseKey"); _pfnDiGetClassDevs = (PROC_DiGetClassDevs)GetProcAddress(g_hInstSetupx, "DiGetClassDevs"); _pfnDiSelectDevice = (PROC_DiSelectDevice)GetProcAddress(g_hInstSetupx, "DiSelectDevice"); _pfnDiBuildCompatDrvList = (PROC_DiBuildCompatDrvList)GetProcAddress(g_hInstSetupx, "DiBuildCompatDrvList"); _pfnDiCreateDevRegKey = (PROC_DiCreateDevRegKey)GetProcAddress(g_hInstSetupx, "DiCreateDevRegKey"); _pfnDiDeleteDevRegKey = (PROC_DiDeleteDevRegKey)GetProcAddress(g_hInstSetupx, "DiDeleteDevRegKey"); } g_cSetupxInit++; return TRUE; } void UninitSetupx() { if (g_cSetupxInit > 0) g_cSetupxInit--; if (g_cSetupxInit == 0) { if (g_hInstSetupx != NULL) { FreeLibrary(g_hInstSetupx); g_hInstSetupx = NULL; } } } extern "C" int FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSeg, WORD wHeapSize, LPSTR lpszCmdLine) { if (wHeapSize != 0) { // UnlockData is no longer #defined to UnlockSegment(-1) in windows.h, // so do it manually here: // //UnlockData(0); UnlockSegment(-1); } return 1; } extern "C" BOOL FAR PASCAL __export DllEntryPoint(DWORD dwReason, WORD hInstance, WORD wDS, WORD wHeapSize, DWORD dwReserved1, WORD wReserved2) { if (!thk_ThunkConnect16( "NCXP16.DLL", "NCXP32.DLL", hInstance, dwReason)) { return FALSE; } return TRUE; } extern "C" int CALLBACK WEP(int nExitType) { return TRUE; } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// #define ASSERT(x) // Local function declarations DWORD CallClassInstaller(HWND hwndParent, LPCSTR lpszClassName, LPCSTR lpszDeviceID); DWORD BindProtocolToAdapters(HWND hwndParent, LPCSTR lpszClassName, LPCSTR lpszDeviceID); ////////////////////////////////////////////////////////////////////////////// // String constants // TODO: clean these up... most of them aren't used any more // Device Manager class names const char szClassNetCard[] = "Net"; const char szClassNetClient[] = "NetClient"; const char szClassNetProtocol[] = "NetTrans"; const char szClassModem[] = "Modem"; // Device ID string constants const char szMSTCPIP_ID[] = "MSTCP"; const char szPPPMAC_ID[] = "*PNP8387"; const char szVREDIR_ID[] = "VREDIR"; const char szNWREDIR_ID[] = "NWREDIR"; const char szIPX_ID[] = "NWLINK"; const char szNETBEUI_ID[] = "NETBEUI"; // Registry string constants const char szRegValSlowNet[] = "SLOWNET"; const char szRegKeyNdi[] = "Ndi"; const char szRegValDeviceID[] = "DeviceID"; const char szRegKeyBindings[] = "Bindings"; const char szRegPathOptComponents[]=REGSTR_PATH_SETUP REGSTR_KEY_SETUP "\\OptionalComponents"; const char szRegValInstalled[] = "Installed"; const char szRegPathNetwork[] = "Enum\\Network"; const char szRegPathTemp[] = "\\Temp"; const char szRegValCompatibleIDs[]= REGSTR_VAL_COMPATIBLEIDS; const char szRegValDeviceType[] = REGSTR_VAL_DEVTYPE; const char szRegValConfigFlags[] = REGSTR_VAL_CONFIGFLAGS; const char szRegPathPlusSetup[] = "Software\\Microsoft\\Plus!\\Setup"; const char szRegValSourcePath[] = "SourcePath"; const char szRegValHardwareID[] = "HardwareID"; // component string constants const char szCompRNA[] = "RNA"; const char szCompMail[] = "MAPI"; const char szCompMSN[] = "MSNetwork"; const char szCompMSN105[] = "MSNetwork105"; const char szCompInetMail[] = "InternetMail"; const char szINF[] = "INF"; const char szSection[] = "Section"; // INF string constants const char szValSignature[] = "$CHICAGO$"; const char szKeySignature[] = "signature"; const char szSectVersion[] = "version"; // other strings const char szNull[] = ""; const char sz1[] = "1"; const char szSlash[] = "\\"; ////////////////////////////////////////////////////////////////////////////// // CreateTempDevRegKey // // Creates a temporary registry key for the device installer. // // History: // // 2/02/1999 KenSh Borrowed from ICW, which borrowed it from net setup // RETERR CreateTempDevRegKey(LPDEVICE_INFO lpdi,LPHKEY lphk) { lpdi->hRegKey = HKEY_LOCAL_MACHINE; lstrcpy(lpdi->szRegSubkey, szRegPathNetwork); lstrcat(lpdi->szRegSubkey, szSlash); lstrcat(lpdi->szRegSubkey, lpdi->szClassName); lstrcat(lpdi->szRegSubkey, szRegPathTemp); InitSetupx(); RETERR err = (*_pfnDiCreateDevRegKey)(lpdi, lphk, NULL, NULL, DIREG_DEV); UninitSetupx(); return err; } // CallClassInstaller // // Calls DiCallClassInstaller for the specified class to install // the specified device ID // // Returns ICERR_xxx return value, defined in NetSetup.h // // Parameters: // // hwndParent - parent window handle // lpszClassName - name of device class (e.g. "NetTrans" or "Net") // lpszDeviceID - unique device ID to install (e.g. "MSTCP" or "PCI\VEN_10b7&DEV_5950" // // History: // // 2/02/1999 KenSh Borrowed from ICW, changed return codes for JetNet // 3/18/1999 KenSh Cleaned up // extern "C" DWORD WINAPI __export CallClassInstaller16(HWND hwndParent, LPCSTR lpszClassName, LPCSTR lpszDeviceID) { RETERR err; DWORD dwResult = ICERR_OK; LPDEVICE_INFO lpdi; HKEY hKeyTmp; LONG uErr; ASSERT(lpszClassName != NULL); ASSERT(lpszDeviceID != NULL); if (!InitSetupx()) return ICERR_DI_ERROR; // allocate a DEVICE_INFO struct err = (*_pfnDiCreateDeviceInfo)(&lpdi, NULL, 0, NULL, NULL, lpszClassName, hwndParent); ASSERT(err == OK); if (err != OK) { lpdi = NULL; goto exit; } // since the device manager APIs are not very good, to communicate the // device ID to it we have to create a temporary registry key and // store the device ID there. This code borrowed from net setup // which has to do the same thing (fill out an LPDEVICE_INFO based // on a device ID) err = CreateTempDevRegKey(lpdi, &hKeyTmp); ASSERT (err == OK); if (err != OK) goto exit; // set the device ID in the registry uErr = RegSetValueEx(hKeyTmp, szRegValCompatibleIDs, 0, REG_SZ, (LPBYTE)lpszDeviceID, lstrlen(lpszDeviceID)+1); ASSERT(uErr == ERROR_SUCCESS); // now call device mgr API to add driver node lists and fill out structure, // it will use the device ID we stuffed in registry. err = (*_pfnDiBuildCompatDrvList)(lpdi); ASSERT(err == OK); RegCloseKey(hKeyTmp); // need to delete temp key, set handle to null, set subkey name to // null or else net setup thinks this device already exists and // zany hijinks ensue (*_pfnDiDeleteDevRegKey)(lpdi, DIREG_DEV); lpdi->hRegKey = NULL; lstrcpy(lpdi->szRegSubkey, szNull); if (err == OK) { lpdi->lpSelectedDriver = lpdi->lpCompatDrvList; ASSERT(lpdi->lpSelectedDriver); err = (*_pfnDiCallClassInstaller)(DIF_INSTALLDEVICE, lpdi); ASSERT(err == OK); if (err == OK) { // if we need to reboot, set a special return code NEED_RESTART // (which also implies success) if (lpdi->Flags & DI_NEEDREBOOT) { // REVIEW: does this need to reboot, or is restart sufficient? // err = NEED_RESTART; dwResult = ICERR_NEED_RESTART; } } } exit: if (lpdi != NULL) (*_pfnDiDestroyDeviceInfoList)(lpdi); if (err != OK) dwResult = ICERR_DI_ERROR | (DWORD)err; UninitSetupx(); return dwResult; } extern "C" HRESULT WINAPI __export FindClassDev16(HWND hwndParent, LPCSTR pszClass, LPCSTR pszDeviceID) { DWORD hr = S_FALSE; LPDEVICE_INFO lpdi; RETERR err; if (!InitSetupx()) return E_FAIL; if (OK != (err = (*_pfnDiGetClassDevs)(&lpdi, pszClass, NULL, DIGCF_PRESENT))) { UninitSetupx(); return E_FAIL; } // This is 16-bit code, so these pnp ids are ANSI only // LPSTR pszAlternateDeviceID = new char[lstrlen(pszDeviceID) + 1]; if (pszAlternateDeviceID) { lstrcpy(pszAlternateDeviceID, pszDeviceID); LPCSTR szSubsysString = "SUBSYS_"; const int nSubsysIDLength = 8; LPSTR pszSubsys = strstri(pszAlternateDeviceID, szSubsysString); if(NULL != pszSubsys) { pszSubsys += _countof("SUBSYS_") - 1; if(nSubsysIDLength <= lstrlen(pszSubsys)) { for(int i = 0; i < nSubsysIDLength; i++) { pszSubsys[i] = '0'; } } } for (LPDEVICE_INFO lpdiCur = lpdi; lpdiCur != NULL; lpdiCur = lpdiCur->lpNextDi) { char szBuf[1024]; // wsprintf(szBuf, "System\\CurrentControlSet\\Services\\Class\\%s\\%04d", pszClass, (int)lpdiCur->dnDevnode); // MessageBox(NULL, szBuf, "RegKey", MB_OK); HKEY hKey; if (OK == (*_pfnDiOpenDevRegKey)(lpdiCur, &hKey, DIREG_DEV)) { static const LPCSTR c_rgRegEntries[] = { "HardwareID", "CompatibleIDs" }; for (int i = 0; i < _countof(c_rgRegEntries); i++) { LONG cbBuf = sizeof(szBuf); if (ERROR_SUCCESS == RegQueryValueEx(hKey, c_rgRegEntries[i], NULL, NULL, (LPBYTE)szBuf, &cbBuf)) { // char szBuf2[1600]; // wsprintf(szBuf2, "Looking for: %s\n\n%s", pszDeviceID, szBuf); // MessageBox(NULL, szBuf2, c_rgRegEntries[i], MB_OK); // aslo check with SUBSYS 00000000 for bug 124967 if (NULL != strstri(szBuf, pszDeviceID) || NULL != strstri(szBuf, pszAlternateDeviceID)) { hr = S_OK; break; } } } RegCloseKey(hKey); } if (hr == S_OK) break; } delete [] pszAlternateDeviceID; } (*_pfnDiDestroyDeviceInfoList)(lpdi); UninitSetupx(); return hr; } extern "C" HRESULT WINAPI __export LookupDevNode16(HWND hwndParent, LPCSTR pszClass, LPCSTR pszEnumKey, DEVNODE FAR* pDevNode, DWORD FAR* pdwFreePointer) { DWORD hr = S_FALSE; LPDEVICE_INFO lpdi; RETERR err; // MessageBox(hwndParent, "LookupDevNode16", "Debug", MB_ICONINFORMATION); if (pDevNode == NULL || pdwFreePointer == NULL) { // MessageBox(hwndParent, "Returning failure 0", "Debug", 0); return E_POINTER; } *pDevNode = 0; *pdwFreePointer = 0; if (!InitSetupx()) { // MessageBox(hwndParent, "Returning failure 1", "Debug", 0); return E_FAIL; } if (OK != (err = (*_pfnDiGetClassDevs)(&lpdi, pszClass, NULL, DIGCF_PRESENT))) { // MessageBox(hwndParent, "Returning failure 2", "Debug", 0); UninitSetupx(); return E_FAIL; } for (LPDEVICE_INFO lpdiCur = lpdi; lpdiCur != NULL; lpdiCur = lpdiCur->lpNextDi) { // char szBuf[1024]; // wsprintf(szBuf, "comparing:\nlpdiCur->pszRegSubkey = \"%s\"\npszEnumKey = \"%s\"", // (LPSTR)lpdiCur->szRegSubkey, (LPSTR)pszEnumKey); // MessageBox(hwndParent, szBuf, "Debug", MB_ICONINFORMATION); if (0 == lstrcmpi(lpdiCur->szRegSubkey, pszEnumKey)) { // wsprintf(szBuf, "found devnode 0x%08lX, pvFreePointer = 0x%08lX", (DWORD)lpdiCur->dnDevnode, (DWORD)lpdi); // MessageBox(hwndParent, szBuf, "Debug", MB_ICONINFORMATION); *pDevNode = lpdiCur->dnDevnode; *pdwFreePointer = (DWORD)lpdi; return S_OK; } } (*_pfnDiDestroyDeviceInfoList)(lpdi); UninitSetupx(); // MessageBox(hwndParent, "returning failure", "Debug", MB_ICONINFORMATION); return E_FAIL; // not found } extern "C" HRESULT WINAPI __export FreeDevNode16(DWORD dwFreePointer) { LPDEVICE_INFO lpdi = (LPDEVICE_INFO)dwFreePointer; if (lpdi == NULL) { return E_INVALIDARG; } if (g_hInstSetupx == NULL) { return E_FAIL; } // char szBuf[1024]; // wsprintf(szBuf, "FreeDevNode16 - freeing lpdi 0x%08lX - continue?", dwFreePointer); // if (IDYES == MessageBox(NULL, szBuf, "Debug", MB_YESNO | MB_ICONEXCLAMATION)) { (*_pfnDiDestroyDeviceInfoList)(lpdi); } UninitSetupx(); return S_OK; } extern "C" HRESULT WINAPI __export IcsUninstall16(void) { typedef void (WINAPI *RUNDLLPROC)(HWND hwndStub, HINSTANCE hAppInstance, LPSTR lpszCmdLine, int nCmdShow); HINSTANCE hInstance = LoadLibrary("issetup.dll"); if(hInstance > 32) { RUNDLLPROC pExtUninstall = (RUNDLLPROC) GetProcAddress(hInstance, "ExtUninstall"); if(NULL != pExtUninstall) { pExtUninstall(NULL, NULL, NULL, 0); } FreeLibrary(hInstance); } return S_OK; }