13 #include "lanahelper.h"
16 extern "C" void afsi_log(...);
18 static HRESULT getname_shellfolder(WCHAR *wGuid, WCHAR *wName, int NameSize)
20 // This is the GUID for the network connections folder. It is constant.
21 // {7007ACC7-3202-11D1-AAD2-00805FC1270E}
22 const GUID CLSID_NetworkConnections = {
23 0x7007ACC7, 0x3202, 0x11D1, {
24 0xAA, 0xD2, 0x00, 0x80, 0x5F, 0xC1, 0x27, 0x0E
28 IShellFolder *pShellFolder;
29 IMalloc *pShellMalloc;
31 // Build the display name in the form "::{GUID}".
32 if (wcslen(wGuid) >= MAX_PATH)
34 WCHAR szAdapterGuid[MAX_PATH + 2];
35 swprintf(szAdapterGuid, L"::%ls", wGuid);
40 // Get the shell allocator.
41 HRESULT hr = SHGetMalloc(&pShellMalloc);
43 // Create an instance of the network connections folder.
44 hr = CoCreateInstance(CLSID_NetworkConnections, NULL,
45 CLSCTX_INPROC_SERVER, IID_IShellFolder,
46 reinterpret_cast<LPVOID *>(&pShellFolder));
48 hr = pShellFolder->ParseDisplayName(NULL, NULL, szAdapterGuid, NULL,
51 // Get the display name; this returns the friendly name.
53 hr = pShellFolder->GetDisplayNameOf(pidl, SHGDN_NORMAL, &sName);
55 wcsncpy(wName, sName.pOleStr, NameSize);
56 pShellMalloc->Free(pidl);
63 // Get the Connection Name for the given GUID.
64 extern "C" int lana_GetNameFromGuid(char *Guid, char **Name)
66 typedef HRESULT (WINAPI *HrLanProcAddr)(GUID *, PCWSTR, PWSTR, LPDWORD);
67 HrLanProcAddr HrLanProc = NULL;
71 WCHAR wName[MAX_PATH];
72 DWORD NameSize = MAX_PATH;
76 // Convert the Guid string to Unicode. First we ask only for the size
77 // of the converted string. Then we allocate a buffer of sufficient
78 // size to hold the result of the conversion.
79 size = MultiByteToWideChar(CP_ACP, 0, Guid, -1, NULL, 0);
80 wGuid = (WCHAR *) malloc(size * sizeof(WCHAR));
81 MultiByteToWideChar(CP_ACP, 0, Guid, -1, wGuid, size);
83 // First try the IShellFolder interface, which was unimplemented
84 // for the network connections folder before XP.
86 /* XXX pbh 9/11/03 - revert to using the undocumented APIs on XP while
87 * waiting to hear back from PSS about the slow reboot issue.
88 * This is an ugly, misleading hack, but is minimally invasive
89 * and will be easy to rollback.
92 //status = getname_shellfolder(wGuid, wName, NameSize);
95 /* XXX end of pbh 9/11/03 temporary hack*/
97 if (status == E_NOTIMPL) {
98 // The IShellFolder interface is not implemented on this platform.
99 // Try the (undocumented) HrLanConnectionNameFromGuidOrPath API
100 // from the netman DLL.
101 afsi_log("IShellFolder API not implemented, trying HrLanConnectionNameFromGuidOrPath");
102 hNetMan = LoadLibrary("netman.dll");
103 if (hNetMan == NULL) {
107 HrLanProc = (HrLanProcAddr) GetProcAddress(hNetMan,
108 "HrLanConnectionNameFromGuidOrPath");
109 if (HrLanProc == NULL) {
110 FreeLibrary(hNetMan);
114 status = HrLanProc(NULL, wGuid, wName, &NameSize);
115 FreeLibrary(hNetMan);
118 if (FAILED(status)) {
119 afsi_log("lana_GetNameFromGuid: failed to get connection name (status %ld)",
124 // Get the required buffer size, and then convert the string.
125 size = WideCharToMultiByte(CP_ACP, 0, wName, -1, NULL, 0, NULL, NULL);
126 name = (char *) malloc(size);
129 WideCharToMultiByte(CP_ACP, 0, wName, -1, name, size, NULL, NULL);
130 afsi_log("Connection name for %s is '%s'", Guid, name);
138 // Find the lana number for the given connection name.
139 extern "C" lana_number_t lana_FindLanaByName(const char *LanaName)
141 const char RegNetBiosLinkageKeyName[] =
142 "System\\CurrentControlSet\\Services\\NetBios\\Linkage";
148 } lanamap[MAX_LANA+1];
149 DWORD lanamapsize = sizeof(lanamap);
151 char *bindpaths = NULL;
160 // Open the NetBios Linkage key.
161 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, RegNetBiosLinkageKeyName, 0,
162 KEY_QUERY_VALUE, &hkey);
164 if (status != ERROR_SUCCESS) {
165 afsi_log("Failed to open NetBios Linkage key (status %ld)", status);
169 // Read the lana map.
170 status = RegQueryValueEx(hkey, "LanaMap", 0, &type,
171 (BYTE *) &lanamap, &lanamapsize);
172 if (status != ERROR_SUCCESS) {
173 afsi_log("Failed to read LanaMap (status %ld)", status);
177 if (lanamapsize == 0) {
178 afsi_log("No data in LanaMap");
181 nlana = lanamapsize / sizeof(lanamap[0]);
183 // Get the bind paths for NetBios so we can match them up
184 // with the lana map. First we query for the size, so we
185 // can allocate an appropriate buffer.
186 status = RegQueryValueEx(hkey, "Bind", 0, &type, NULL, &bindpathsize);
187 if (status == ERROR_SUCCESS && bindpathsize != 0) {
188 bindpaths = (char *) malloc(bindpathsize * sizeof(char));
189 if (bindpaths == NULL) {
190 afsi_log("Cannot allocate %ld bytes for bindpaths", bindpathsize);
194 status = RegQueryValueEx(hkey, "Bind", 0, &type,
195 (BYTE *) bindpaths, &bindpathsize);
198 if (status != ERROR_SUCCESS) {
199 afsi_log("Failed to read bind paths (status %ld)", status);
200 if (bindpaths != NULL)
204 if (bindpathsize == 0) {
205 afsi_log("No bindpath data");
206 if (bindpaths != NULL)
211 // Iterate over the lana map entries and bind paths.
212 for (i = 0, pBind = bindpaths; i < nlana;
213 i++, pBind += strlen(pBind) + 1) {
214 // Ignore an invalid map entry.
215 if ((lanamap[i].flags & 1) == 0)
218 // check for a IPv4 binding
219 if(!strstr(pBind,"_Tcpip_"))
222 // Find the beginning of the GUID.
223 guid = strchr(pBind, '{');
225 continue; // Malformed path entry?
229 // Find the end of the GUID.
230 p = strchr(guid, '}');
232 free(guid); // Malformed GUID?
235 *++p = '\0'; // Ignore anything after the GUID.
236 status = lana_GetNameFromGuid(guid, &name);
238 if (status == 0 && name != 0) {
239 status = strcmp(name, LanaName);
243 afsi_log("lana_FindLanaByName: Found lana %d for %s",
244 lanamap[i].number, LanaName);
245 return lanamap[i].number;
253 extern "C" lana_number_t lana_FindLoopback(void)
260 memset(&ncb, 0, sizeof(ncb));
261 ncb.ncb_command = NCBENUM;
262 ncb.ncb_buffer = (UCHAR *) &lana_list;
263 ncb.ncb_length = sizeof(lana_list);
264 status = Netbios(&ncb);
266 afsi_log("Netbios NCBENUM failed: status %ld", status);
269 for (i = 0; i < lana_list.length; i++) {
270 if (lana_IsLoopback(lana_list.lana[i])) {
271 // Found one, return it.
272 afsi_log("lana_FindLoopback: Found LAN adapter %d",
274 return lana_list.lana[i];
277 // Could not find a loopback adapter.
281 // Is the given lana a Windows Loopback Adapter?
282 extern "C" BOOL lana_IsLoopback(lana_number_t lana)
286 ADAPTER_STATUS status;
287 NAME_BUFFER names[MAX_LANA+1];
289 unsigned char kWLA_MAC[6] = { 0x02, 0x00, 0x4c, 0x4f, 0x4f, 0x50 };
292 // Reset the adapter: in Win32, this is required for every process, and
293 // acts as an init call, not as a real hardware reset.
294 memset(&ncb, 0, sizeof(ncb));
295 ncb.ncb_command = NCBRESET;
296 ncb.ncb_callname[0] = 100;
297 ncb.ncb_callname[2] = 100;
298 ncb.ncb_lana_num = lana;
299 status = Netbios(&ncb);
301 status = ncb.ncb_retcode;
303 afsi_log("NCBRESET failed: lana %u, status %ld", lana, status);
307 // Use the NCBASTAT command to get the adapter address.
308 memset(&ncb, 0, sizeof(ncb));
309 ncb.ncb_command = NCBASTAT;
310 ncb.ncb_lana_num = lana;
311 strcpy((char *) ncb.ncb_callname, "* ");
312 ncb.ncb_buffer = (UCHAR *) &astat;
313 ncb.ncb_length = sizeof(astat);
314 status = Netbios(&ncb);
316 status = ncb.ncb_retcode;
317 if (ncb.ncb_retcode != 0) {
318 afsi_log("NCBASTAT failed: lana %u, status %ld", lana, status);
321 return (memcmp(astat.status.adapter_address, kWLA_MAC, 6) == 0);