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 = (sizeof(wName) / sizeof(wName[0]));
75 // Convert the Guid string to Unicode. First we ask only for the size
76 // of the converted string. Then we allocate a buffer of sufficient
77 // size to hold the result of the conversion.
78 size = MultiByteToWideChar(CP_ACP, 0, Guid, -1, NULL, 0);
79 wGuid = (WCHAR *) malloc(size * sizeof(WCHAR));
80 MultiByteToWideChar(CP_ACP, 0, Guid, -1, wGuid, size);
82 // First try the IShellFolder interface, which was unimplemented
83 // for the network connections folder before XP.
85 /* XXX pbh 9/11/03 - revert to using the undocumented APIs on XP while
86 * waiting tohear back from PSS about the slow reboot issue.
87 * This is an ungly, misleading hack, but is minimally invasive
88 * and will be easy to rollback.
91 //status = getname_shellfolder(wGuid, wName, NameSize);
94 /* XXX end of pbh 9/11/03 temporary hack*/
96 if (status == E_NOTIMPL) {
97 // The IShellFolder interface is not implemented on this platform.
98 // Try the (undocumented) HrLanConnectionNameFromGuidOrPath API
99 // from the netman DLL.
100 afsi_log("IShellFolder API not implemented, trying HrLanConnectionNameFromGuidOrPath");
101 hNetMan = LoadLibrary("netman.dll");
102 if (hNetMan == NULL) {
107 (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);
134 // Find the lana number for the given connection name.
135 extern "C" lana_number_t lana_FindLanaByName(const char *LanaName)
137 const char RegNetBiosLinkageKeyName[] =
138 "System\\CurrentControlSet\\Services\\NetBios\\Linkage";
144 } lanamap[MAX_LANA+1];
145 DWORD lanamapsize = sizeof(lanamap);
147 char *bindpaths = NULL;
156 // Open the NetBios Linkage key.
157 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, RegNetBiosLinkageKeyName, 0,
158 KEY_QUERY_VALUE, &hkey);
160 if (status != ERROR_SUCCESS) {
161 afsi_log("Failed to open NetBios Linkage key (status %ld)", status);
165 // Read the lana map.
166 status = RegQueryValueEx(hkey, "LanaMap", 0, &type,
167 (BYTE *) &lanamap, &lanamapsize);
168 if (status != ERROR_SUCCESS) {
169 afsi_log("Failed to read LanaMap (status %ld)", status);
173 if (lanamapsize == 0) {
174 afsi_log("No data in LanaMap");
177 nlana = lanamapsize / sizeof(lanamap[0]);
179 // Get the bind paths for NetBios so we can match them up
180 // with the lana map. First we query for the size, so we
181 // can allocate an appropriate buffer.
182 status = RegQueryValueEx(hkey, "Bind", 0, &type, NULL, &bindpathsize);
183 if (status == ERROR_SUCCESS && bindpathsize != 0) {
184 bindpaths = (char *) malloc(bindpathsize * sizeof(char));
185 if (bindpaths == NULL) {
186 afsi_log("Cannot allocate %ld bytes for bindpaths", bindpathsize);
190 status = RegQueryValueEx(hkey, "Bind", 0, &type,
191 (BYTE *) bindpaths, &bindpathsize);
194 if (status != ERROR_SUCCESS) {
195 afsi_log("Failed to read bind paths (status %ld)", status);
196 if (bindpaths != NULL)
200 if (bindpathsize == 0) {
201 afsi_log("No bindpath data");
202 if (bindpaths != NULL)
207 // Iterate over the lana map entries and bind paths.
208 for (i = 0, pBind = bindpaths; i < nlana;
209 i++, pBind += strlen(pBind) + 1) {
210 // Ignore an invalid map entry.
211 if ((lanamap[i].flags & 1) == 0)
214 // check for a IPv4 binding
215 if(!strstr(pBind,"_Tcpip_"))
218 // Find the beginning of the GUID.
219 guid = strchr(pBind, '{');
221 continue; // Malformed path entry?
225 // Find the end of the GUID.
226 p = strchr(guid, '}');
228 free(guid); // Malformed GUID?
231 *++p = '\0'; // Ignore anything after the GUID.
232 status = lana_GetNameFromGuid(guid, &name);
235 status = strcmp(name, LanaName);
239 afsi_log("lana_FindLanaByName: Found lana %d for %s",
240 lanamap[i].number, LanaName);
241 return lanamap[i].number;
249 extern "C" lana_number_t lana_FindLoopback(void)
256 memset(&ncb, 0, sizeof(ncb));
257 ncb.ncb_command = NCBENUM;
258 ncb.ncb_buffer = (UCHAR *) &lana_list;
259 ncb.ncb_length = sizeof(lana_list);
260 status = Netbios(&ncb);
262 afsi_log("Netbios NCBENUM failed: status %ld", status);
265 for (i = 0; i < lana_list.length; i++) {
266 if (lana_IsLoopback(lana_list.lana[i])) {
267 // Found one, return it.
268 afsi_log("lana_FindLoopback: Found LAN adapter %d",
270 return lana_list.lana[i];
273 // Could not find a loopback adapter.
277 // Is the given lana a Windows Loopback Adapter?
278 extern "C" BOOL lana_IsLoopback(lana_number_t lana)
282 ADAPTER_STATUS status;
283 NAME_BUFFER names[MAX_LANA+1];
285 unsigned char kWLA_MAC[6] = { 0x02, 0x00, 0x4c, 0x4f, 0x4f, 0x50 };
288 // Reset the adapter: in Win32, this is required for every process, and
289 // acts as an init call, not as a real hardware reset.
290 memset(&ncb, 0, sizeof(ncb));
291 ncb.ncb_command = NCBRESET;
292 ncb.ncb_callname[0] = 100;
293 ncb.ncb_callname[2] = 100;
294 ncb.ncb_lana_num = lana;
295 status = Netbios(&ncb);
297 status = ncb.ncb_retcode;
299 afsi_log("NCBRESET failed: lana %u, status %ld", lana, status);
303 // Use the NCBASTAT command to get the adapter address.
304 memset(&ncb, 0, sizeof(ncb));
305 ncb.ncb_command = NCBASTAT;
306 ncb.ncb_lana_num = lana;
307 strcpy((char *) ncb.ncb_callname, "* ");
308 ncb.ncb_buffer = (UCHAR *) &astat;
309 ncb.ncb_length = sizeof(astat);
310 status = Netbios(&ncb);
312 status = ncb.ncb_retcode;
313 if (ncb.ncb_retcode != 0) {
314 afsi_log("NCBASTAT failed: lana %u, status %ld", lana, status);
317 return (memcmp(astat.status.adapter_address, kWLA_MAC, 6) == 0);