#include "stdafx.h" #include "AtlkAdapter.h" #include "ndispnpevent.h" HRESULT CAtlkAdapter::Initialize() { HRESULT hr; hr = ValidateAdapGuid(); if(hr != S_OK) return hr; hr = UpdateZoneList(); if(hr != S_OK) return hr; UpdateDesiredZone(); m_bstrNewDesiredZone = m_bstrDesiredZone; return hr; } VOID CAtlkAdapter::GetZoneList(TZoneListVector *pZonesList) { *pZonesList = m_ZonesList; } HRESULT CAtlkAdapter::SetAsDefaultPort() { HRESULT hr=S_OK; if(m_bDefaultPort) return hr; if( (hr = SetDefaultPortInReg()) != S_OK) return hr; m_bDefPortDirty = TRUE; return AtlkReconfig(); } HRESULT CAtlkAdapter::SetDesiredZone(BSTR bstrZoneName) { HRESULT hr=S_OK; ULONG ulIndex; for(ulIndex=0; ulIndex < m_ZonesList.size(); ulIndex++) { wstring ZoneName; ZoneName = m_ZonesList[ulIndex]; if(!lstrcmpi(ZoneName.c_str(), bstrZoneName)) { break; } } if(ulIndex == m_ZonesList.size()) return E_INVALIDARG; //invalid zone name specified if(!m_bDefaultPort) { if( (hr = SetDefaultPortInReg()) != S_OK) return hr; m_bDefPortDirty = TRUE; } if(!lstrcmpi(m_bstrDesiredZone.m_str, bstrZoneName)) return hr; //already is the desired zone just return m_bstrNewDesiredZone = bstrZoneName; if( (hr=SetDesiredZoneInReg()) != S_OK) return hr; m_bDesZoneDirty = TRUE; return AtlkReconfig(); } //private method //check whether this adapter is configured for appletalk HRESULT CAtlkAdapter::ValidateAdapGuid() { HKEY hAdRegKey = NULL; HRESULT hr = S_OK; DWORD dwDataSize, dwType; LPBYTE pDataBuffer = NULL; WCHAR *szAdapGuid; try { LONG lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szATLKLinkage,0, KEY_QUERY_VALUE, &hAdRegKey); if(lRet != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lRet); throw hr; } lRet = RegQueryValueEx(hAdRegKey, c_szRoute, NULL, NULL, NULL, &dwDataSize); if(lRet != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lRet); throw hr; } pDataBuffer = new BYTE[dwDataSize]; if(pDataBuffer == NULL) { hr = E_OUTOFMEMORY; throw hr; } lRet = RegQueryValueEx(hAdRegKey, c_szRoute, NULL, &dwType, pDataBuffer, &dwDataSize); if(lRet != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lRet); throw hr; } szAdapGuid = (WCHAR *) pDataBuffer; hr = E_INVALIDARG; while(szAdapGuid[0] != _TEXT('\0')) { if( wcsstr (szAdapGuid, m_bstrAdapGuid.m_str) ) { hr = S_OK; break; } szAdapGuid = szAdapGuid + lstrlen(szAdapGuid) + 1; } } catch( ... ) { } if ( pDataBuffer ) delete [] pDataBuffer; return hr; } //private method HRESULT CAtlkAdapter::UpdateZoneList() { HRESULT hr = S_OK; WCHAR *szAppTalkAd = NULL; HKEY hAdRegKey = NULL; LPBYTE pZoneBuffer=NULL; DWORD dwDataSize; DWORD dwType; WCHAR *szZone; try { //read the zonelist from registry and add to global zone list szAppTalkAd = new WCHAR[m_bstrAdapGuid.Length() + lstrlen(c_szATLKAdapters) + 10]; if(szAppTalkAd == NULL ) { hr = E_OUTOFMEMORY; throw hr; } wsprintf(szAppTalkAd, L"%s\\%s",c_szATLKAdapters,m_bstrAdapGuid.m_str); LONG lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szAppTalkAd,0, KEY_QUERY_VALUE, &hAdRegKey); if(lRet != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lRet); throw hr; } lRet = RegQueryValueEx(hAdRegKey, c_szZoneList, NULL, NULL, NULL, &dwDataSize); if(lRet != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lRet); throw hr; } pZoneBuffer = new BYTE[dwDataSize]; if(pZoneBuffer == NULL) { hr = E_OUTOFMEMORY; throw hr; } lRet = RegQueryValueEx(hAdRegKey, c_szZoneList, NULL, &dwType, pZoneBuffer, &dwDataSize); if(lRet != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lRet); throw hr; } szZone = (WCHAR *) pZoneBuffer; while(szZone[0] != _TEXT('\0')) { wstring ZoneName(szZone); m_ZonesList.push_back(ZoneName); szZone = szZone + lstrlen(szZone) + 1; } /*if( (hr=UpdateZonesListFromSocket()) != S_OK) throw hr;*/ //return value is not checked beacuse bind fails if the adapter is not the //default port, need to investigate UpdateZonesListFromSocket(); } catch ( ... ) { } if(szAppTalkAd != NULL) delete [] szAppTalkAd; if(pZoneBuffer != NULL) delete [] pZoneBuffer; if(hAdRegKey != NULL) RegCloseKey(hAdRegKey); return hr; } //private method VOID CAtlkAdapter::UpdateDesiredZone() { if(!GetDesiredZoneFromReg()) m_bstrDesiredZone = m_bstrDefZone; } //private method BOOL CAtlkAdapter::GetDesiredZoneFromReg() { HKEY hParmRegKey=NULL; DWORD dwDataSize; DWORD dwType; LPBYTE pZoneData; BOOL bRetVal = FALSE; WCHAR *szAppTalkAd; HKEY hAdRegKey=NULL; try { LONG lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szATLKParameters,0, KEY_QUERY_VALUE, &hParmRegKey); if(lRet != ERROR_SUCCESS) { throw bRetVal; } lRet = RegQueryValueEx(hParmRegKey, c_szDefaultPort, NULL, NULL, NULL, &dwDataSize); if(lRet != ERROR_SUCCESS) { throw bRetVal; } pZoneData = new BYTE[dwDataSize]; if(pZoneData == NULL) { bRetVal = FALSE; throw bRetVal; } lRet = RegQueryValueExW(hParmRegKey, c_szDefaultPort, NULL, &dwType, pZoneData, &dwDataSize); if(lRet != ERROR_SUCCESS) { throw bRetVal; } if(!lstrcmpi(m_bstrPortName.m_str, (WCHAR*)pZoneData)) { //this adapter is the default port, so also update the flag m_bDeafultPort to true delete [] pZoneData; pZoneData = NULL; m_bDefaultPort = TRUE; lRet = RegQueryValueEx(hParmRegKey, c_szDesiredZone, NULL, NULL, NULL, &dwDataSize); if(lRet != ERROR_SUCCESS) { throw bRetVal; } pZoneData = new BYTE[dwDataSize]; lRet = RegQueryValueEx(hParmRegKey, c_szDesiredZone, NULL, &dwType, pZoneData, &dwDataSize); if(lRet == ERROR_SUCCESS) { if( ((WCHAR*)pZoneData)[0] != _TEXT('\0')) { bRetVal = TRUE; m_bstrDesiredZone = (WCHAR*)pZoneData; throw bRetVal; } } } delete [] pZoneData; pZoneData = NULL; //adapter is not the default one, so try to read the default zone from Adapters/GUID reg loc szAppTalkAd = new WCHAR[m_bstrAdapGuid.Length() + lstrlen(c_szATLKAdapters) + 10]; wsprintf(szAppTalkAd, L"%s\\%s",c_szATLKAdapters,m_bstrAdapGuid.m_str); lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szAppTalkAd,0, KEY_QUERY_VALUE, &hAdRegKey); if(lRet != ERROR_SUCCESS) { throw bRetVal; } lRet = RegQueryValueEx(hAdRegKey, c_szDefaultZone, NULL, NULL, NULL, &dwDataSize); if(lRet != ERROR_SUCCESS) { throw bRetVal; } pZoneData = new BYTE[dwDataSize]; lRet = RegQueryValueEx(hAdRegKey, c_szDefaultZone, NULL, &dwType, pZoneData, &dwDataSize); if(lRet != ERROR_SUCCESS) { throw bRetVal; } if( ((WCHAR*)pZoneData)[0] != _TEXT('\0')) { bRetVal = TRUE; m_bstrDesiredZone = (WCHAR*)pZoneData; } } catch(...) { } if(hParmRegKey != NULL) RegCloseKey(hParmRegKey); if(pZoneData) delete [] pZoneData; return bRetVal; } //private method HRESULT CAtlkAdapter::UpdateZonesListFromSocket() { SOCKADDR_AT address; BOOL fWSInitialized = FALSE; SOCKET mysocket = INVALID_SOCKET; WSADATA wsadata; DWORD dwWsaerr; HRESULT hr = S_OK; try { // Create the socket/bind dwWsaerr = WSAStartup(0x0101, &wsadata); if (0 != dwWsaerr) { hr = HRESULT_FROM_WIN32(dwWsaerr); throw hr; } // Winsock successfully initialized fWSInitialized = TRUE; mysocket = socket(AF_APPLETALK, SOCK_DGRAM, DDPPROTO_ZIP); if (INVALID_SOCKET == mysocket) { dwWsaerr = ::WSAGetLastError(); hr = HRESULT_FROM_WIN32(dwWsaerr); throw hr; } address.sat_family = AF_APPLETALK; address.sat_net = 0; address.sat_node = 0; address.sat_socket = 0; dwWsaerr = bind(mysocket, (struct sockaddr *)&address, sizeof(address)); if (dwWsaerr != 0) { dwWsaerr = ::WSAGetLastError(); hr = HRESULT_FROM_WIN32(dwWsaerr); throw hr; } // Failures from query the zone list for a given adapter can be from // the adapter not connected to the network, zone seeder not running, etc. // Because we want to process all the adapters, we ignore these errors. hr = UpdateDefZonesFromSocket(mysocket); } catch( ... ) { } if (INVALID_SOCKET != mysocket) { closesocket(mysocket); } if (fWSInitialized) { WSACleanup(); } return hr; } //private method // // Function: CAtlkAdapter::UpdateDefZonesFromSocket // // Purpose: // // Parameters: // // Returns: DWORD, ERROR_SUCCESS on success // #define PARM_BUF_LEN 512 #define ASTERISK_CHAR "*" HRESULT CAtlkAdapter::UpdateDefZonesFromSocket ( SOCKET socket ) { CHAR *pZoneBuffer = NULL; CHAR *pDefParmsBuffer = NULL; CHAR *pZoneListStart; INT BytesNeeded ; WCHAR *pwDefZone = NULL; INT ZoneLen = 0; DWORD dwWsaerr = ERROR_SUCCESS; CHAR *pDefZone = NULL; HRESULT hr = S_OK; PWSH_LOOKUP_ZONES pGetNetZones; PWSH_LOOKUP_NETDEF_ON_ADAPTER pGetNetDefaults; try { pZoneBuffer = new CHAR [ZONEBUFFER_LEN + sizeof(WSH_LOOKUP_ZONES)]; pGetNetZones = (PWSH_LOOKUP_ZONES)pZoneBuffer; wcscpy((WCHAR *)(pGetNetZones+1), m_bstrPortName.m_str); BytesNeeded = ZONEBUFFER_LEN; dwWsaerr = getsockopt(socket, SOL_APPLETALK, SO_LOOKUP_ZONES_ON_ADAPTER, (char *)pZoneBuffer, &BytesNeeded); if (0 != dwWsaerr) { hr = HRESULT_FROM_WIN32(dwWsaerr); throw hr; } pZoneListStart = pZoneBuffer + sizeof(WSH_LOOKUP_ZONES); if (!lstrcmpA(pZoneListStart, ASTERISK_CHAR)) { // Success, wildcard zone set. throw hr; } dwWsaerr = UpdateDefZonesToZoneList(pZoneListStart, ((PWSH_LOOKUP_ZONES)pZoneBuffer)->NoZones); if (dwWsaerr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(dwWsaerr); throw hr; } // // Get the DefaultZone/NetworkRange Information pDefParmsBuffer = new CHAR[PARM_BUF_LEN+sizeof(WSH_LOOKUP_NETDEF_ON_ADAPTER)]; pGetNetDefaults = (PWSH_LOOKUP_NETDEF_ON_ADAPTER)pDefParmsBuffer; BytesNeeded = PARM_BUF_LEN + sizeof(WSH_LOOKUP_NETDEF_ON_ADAPTER); wcscpy((WCHAR*)(pGetNetDefaults+1), m_bstrPortName.m_str); pGetNetDefaults->NetworkRangeLowerEnd = pGetNetDefaults->NetworkRangeUpperEnd = 0; dwWsaerr = getsockopt(socket, SOL_APPLETALK, SO_LOOKUP_NETDEF_ON_ADAPTER, (char*)pDefParmsBuffer, &BytesNeeded); if (0 != dwWsaerr) { #ifdef DBG DWORD dwErr = WSAGetLastError(); #endif hr = HRESULT_FROM_WIN32(dwWsaerr); throw hr; } pDefZone = pDefParmsBuffer + sizeof(WSH_LOOKUP_NETDEF_ON_ADAPTER); ZoneLen = lstrlenA(pDefZone) + 1; pwDefZone = new WCHAR [sizeof(WCHAR) * ZoneLen]; //Assert(NULL != pwDefZone); mbstowcs(pwDefZone, pDefZone, ZoneLen); m_bstrDefZone = pwDefZone; } catch( ... ) { if (pZoneBuffer != NULL) { delete [] pZoneBuffer; } if (pwDefZone != NULL) { delete [] pwDefZone; } if (pDefParmsBuffer != NULL) { delete [] pDefParmsBuffer; } } return hr; } //private method HRESULT CAtlkAdapter::UpdateDefZonesToZoneList(CHAR * szZoneList, ULONG NumZones) { INT cbAscii = 0; ULONG iIndex=0; WCHAR *pszZone = NULL; HRESULT hr = S_OK; while(NumZones--) { cbAscii = lstrlenA(szZoneList) + 1; pszZone = new WCHAR [sizeof(WCHAR) * cbAscii]; if(pszZone == NULL) { hr = E_POINTER; return hr; } mbstowcs(pszZone, szZoneList, cbAscii); for(iIndex=0; iIndex= m_ZonesList.size()) { wstring ZoneName(pszZone); m_ZonesList.push_back(ZoneName); } szZoneList += cbAscii; delete [] pszZone; } return hr; } //private method HRESULT CAtlkAdapter::AtlkReconfig() { HRESULT hrRet = S_OK; ATALK_PNP_EVENT Config; ZeroMemory(&Config, sizeof(Config)); if(m_bDefPortDirty) { // notify atlk Config.PnpMessage = AT_PNP_SWITCH_DEFAULT_ADAPTER; hrRet = HrSendNdisPnpReconfig(NDIS, c_szAtlk, NULL, &Config, sizeof(ATALK_PNP_EVENT)); if (FAILED(hrRet)) { return hrRet; } } if(m_bDesZoneDirty) { Config.PnpMessage = AT_PNP_RECONFIGURE_PARMS; // Now submit the reconfig notification hrRet = HrSendNdisPnpReconfig(NDIS, c_szAtlk, m_bstrAdapGuid.m_str, &Config, sizeof(ATALK_PNP_EVENT)); if (FAILED(hrRet)) { return hrRet; } } return hrRet; } //private method HRESULT CAtlkAdapter::SetDefaultPortInReg() { HRESULT hr=S_OK; HKEY hParamRegKey = NULL; try { LONG lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szATLKParameters,0, KEY_SET_VALUE, &hParamRegKey); if(lRet != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lRet); throw hr; } DWORD dwSize = m_bstrPortName.Length()*sizeof(WCHAR) + 2; lRet = RegSetValueEx(hParamRegKey,c_szDefaultPort,0,REG_SZ,(BYTE *) m_bstrPortName.m_str, dwSize); if(lRet != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lRet); throw hr; } } catch( ... ) { } if(hParamRegKey) RegCloseKey(hParamRegKey); return hr; } //private method HRESULT CAtlkAdapter::SetDesiredZoneInReg() { HRESULT hr=S_OK; HKEY hParamRegKey = NULL; try { if(m_bstrNewDesiredZone[0] == _TEXT('\0')) throw hr; LONG lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szATLKParameters,0, KEY_SET_VALUE, &hParamRegKey); if(lRet != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lRet); throw hr; } DWORD dwSize = m_bstrNewDesiredZone.Length()*sizeof(WCHAR) + 2; lRet = RegSetValueEx(hParamRegKey,c_szDesiredZone,0,REG_SZ,(BYTE *) m_bstrNewDesiredZone.m_str, dwSize); if(lRet != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lRet); throw hr; } } catch( ... ) { } if(hParamRegKey) RegCloseKey(hParamRegKey); return hr; }