1 // getlana.cpp : Defines the entry point for the console application.
22 #define LANA_INVALID 0xff
24 BOOL lana_IsLoopback(lana_number_t lana, TCHAR*);
25 lana_number_t lana_FindLoopback(TCHAR*);
29 // Use the IShellFolder API to get the connection name for the given Guid.
30 static HRESULT getname_shellfolder(WCHAR *wGuid, WCHAR *wName, int NameSize)
32 // This is the GUID for the network connections folder. It is constant.
33 // {7007ACC7-3202-11D1-AAD2-00805FC1270E}
34 const GUID CLSID_NetworkConnections = {
35 0x7007ACC7, 0x3202, 0x11D1, {
36 0xAA, 0xD2, 0x00, 0x80, 0x5F, 0xC1, 0x27, 0x0E
40 IShellFolder *pShellFolder;
41 IMalloc *pShellMalloc;
43 // Build the display name in the form "::{GUID}".
44 if (wcslen(wGuid) >= MAX_PATH)
46 WCHAR szAdapterGuid[MAX_PATH + 2];
47 swprintf(szAdapterGuid, L"::%ls", wGuid);
52 // Get the shell allocator.
53 HRESULT hr = SHGetMalloc(&pShellMalloc);
56 // Create an instance of the network connections folder.
57 hr = CoCreateInstance(CLSID_NetworkConnections, NULL,
58 CLSCTX_INPROC_SERVER, IID_IShellFolder,
59 reinterpret_cast<LPVOID *>(&pShellFolder));
62 hr = pShellFolder->ParseDisplayName(NULL, NULL, szAdapterGuid, NULL,
66 // Get the display name; this returns the friendly name.
68 hr = pShellFolder->GetDisplayNameOf(pidl, SHGDN_NORMAL, &sName);
70 wcsncpy(wName, sName.pOleStr, NameSize);
71 pShellMalloc->Free(pidl);
78 // Get the Connection Name for the given GUID.
79 static int lana_GetNameFromGuid(char *Guid, char **Name)
81 typedef HRESULT (WINAPI *HrLanProcAddr)(GUID *, PCWSTR, PWSTR, LPDWORD);
82 HrLanProcAddr HrLanProc = NULL;
86 WCHAR wName[MAX_PATH];
87 DWORD NameSize = (sizeof(wName) / sizeof(wName[0]));
90 // Convert the Guid string to Unicode. First we ask only for the size
91 // of the converted string. Then we allocate a buffer of sufficient
92 // size to hold the result of the conversion.
93 size = MultiByteToWideChar(CP_ACP, 0, Guid, -1, NULL, 0);
94 wGuid = (WCHAR *) malloc(size * sizeof(WCHAR));
95 MultiByteToWideChar(CP_ACP, 0, Guid, -1, wGuid, size);
97 // First try the IShellFolder interface, which was unimplemented
98 // for the network connections folder before XP.
99 status = getname_shellfolder(wGuid, wName, NameSize);
100 if (status == E_NOTIMPL)
102 // The IShellFolder interface is not implemented on this platform.
103 // Try the (undocumented) HrLanConnectionNameFromGuidOrPath API
104 // from the netman DLL.
105 hNetMan = LoadLibrary("netman.dll");
112 (HrLanProcAddr) GetProcAddress(hNetMan,
113 "HrLanConnectionNameFromGuidOrPath");
114 if (HrLanProc == NULL)
116 FreeLibrary(hNetMan);
120 // Super Secret Microsoft Call
121 status = HrLanProc(NULL, wGuid, wName, &NameSize);
122 FreeLibrary(hNetMan);
127 cerr << "lana_GetNameFromGuid: failed to get connection name (status "
128 << status << ")\r\n";
132 // Get the required buffer size, and then convert the string.
133 size = WideCharToMultiByte(CP_ACP, 0, wName, -1, NULL, 0, NULL, NULL);
134 *Name = (char *) malloc(size);
137 WideCharToMultiByte(CP_ACP, 0, wName, -1, *Name, size, NULL, NULL);
141 LANAINFO* GetLana(TCHAR* msg, const char *LanaName)
143 const char RegNetBiosLinkageKeyName[] =
144 "System\\CurrentControlSet\\Services\\NetBios\\Linkage";
150 } lanamap[MAX_LANA+1];
151 DWORD lanamapsize = sizeof(lanamap);
153 char *bindpaths = NULL;
164 // Open the NetBios Linkage key.
165 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, RegNetBiosLinkageKeyName, 0,
166 KEY_QUERY_VALUE, &hkey);
168 if (status != ERROR_SUCCESS)
170 _stprintf(msg, _T("Failed to open NetBios Linkage key (status %d)"), status);
174 // Read the lana map.
175 status = RegQueryValueEx(hkey, "LanaMap", 0, &type,
176 (BYTE *) &lanamap, &lanamapsize);
177 if (status != ERROR_SUCCESS)
179 _stprintf(msg, _T("Failed to read LanaMap (status %d)"), status);
183 if (lanamapsize == 0)
185 _stprintf(msg, _T("No data in LanaMap"));
188 nlana = lanamapsize / sizeof(lanamap[0]);
190 // Get the bind paths for NetBios so we can match them up
191 // with the lana map. First we query for the size, so we
192 // can allocate an appropriate buffer.
193 status = RegQueryValueEx(hkey, "Bind", 0, &type, NULL, &bindpathsize);
194 if (status == ERROR_SUCCESS && bindpathsize != 0)
196 bindpaths = (char *) malloc(bindpathsize * sizeof(char));
197 if (bindpaths == NULL)
199 _stprintf(msg, _T("Cannot allocate %d bytes for bindpaths"), bindpathsize);
204 status = RegQueryValueEx(hkey, "Bind", 0, &type,
205 (BYTE *) bindpaths, &bindpathsize);
208 if (status != ERROR_SUCCESS)
210 _stprintf(msg, _T("Failed to read bind paths (status %d)"), status);
211 if (bindpaths != NULL)
215 if (bindpathsize == 0)
217 _stprintf(msg, _T("No bindpath data"));
218 if (bindpaths != NULL)
225 lanainfo = new LANAINFO[1];
226 lanainfo[0].lana_number = LANA_INVALID;
227 memset(lanainfo[0].lana_name, 0, sizeof(lanainfo[0].lana_name));
231 lanainfo = new LANAINFO[nlana+1];
232 memset(lanainfo, 0, sizeof(LANAINFO) * nlana);
235 for (i = 0, pBind = bindpaths; i < nlana;
236 i++, pBind += strlen(pBind) + 1)
238 // Ignore an invalid map entry.
239 if ((lanamap[i].flags & 1) == 0)
241 // Find the beginning of the GUID.
242 guid = strchr(pBind, '{');
244 continue; // Malformed path entry?
248 // Find the end of the GUID.
249 p = strchr(guid, '}');
252 free(guid); // Malformed GUID?
255 *++p = '\0'; // Ignore anything after the GUID.
256 status = lana_GetNameFromGuid(guid, &name);
261 if (strcmp(name, LanaName) ==0)
263 lanainfo[index].lana_number = lanamap[i].number;
264 _tcscpy(lanainfo[index].lana_name ,name);
272 lanainfo[index].lana_number = lanamap[i].number;
273 _tcscpy(lanainfo[index].lana_name ,name);
286 lana_number_t lana_FindLoopback(TCHAR* msg)
293 memset(&ncb, 0, sizeof(ncb));
294 ncb.ncb_command = NCBENUM;
295 ncb.ncb_buffer = (UCHAR *) &lana_list;
296 ncb.ncb_length = sizeof(lana_list);
297 status = Netbios(&ncb);
299 _stprintf(msg, _T("Netbios NCBENUM failed: status %ld"), status);
303 for (i = 0; i < lana_list.length; i++) {
304 if (lana_IsLoopback(lana_list.lana[i], msg)) {
305 // Found one, return it.
306 return lana_list.lana[i];
309 // Could not find a loopback adapter.
314 // Is the given lana a Windows Loopback Adapter?
315 BOOL lana_IsLoopback(lana_number_t lana, TCHAR* msg)
319 ADAPTER_STATUS status;
320 NAME_BUFFER names[MAX_LANA+1];
322 unsigned char kWLA_MAC[6] = { 0x02, 0x00, 0x4c, 0x4f, 0x4f, 0x50 };
325 // Reset the adapter: in Win32, this is required for every process, and
326 // acts as an init call, not as a real hardware reset.
327 memset(&ncb, 0, sizeof(ncb));
328 ncb.ncb_command = NCBRESET;
329 ncb.ncb_callname[0] = 100;
330 ncb.ncb_callname[2] = 100;
331 ncb.ncb_lana_num = lana;
332 status = Netbios(&ncb);
334 status = ncb.ncb_retcode;
336 sprintf(msg, "NCBRESET failed: lana %u, status %ld", lana, status);
340 // Use the NCBASTAT command to get the adapter address.
341 memset(&ncb, 0, sizeof(ncb));
342 ncb.ncb_command = NCBASTAT;
343 ncb.ncb_lana_num = lana;
344 strcpy((char *) ncb.ncb_callname, "* ");
345 ncb.ncb_buffer = (UCHAR *) &astat;
346 ncb.ncb_length = sizeof(astat);
347 status = Netbios(&ncb);
349 status = ncb.ncb_retcode;
350 if (ncb.ncb_retcode != 0) {
351 sprintf(msg, "NCBASTAT failed: lana %u, status %ld", lana, status);
354 return (memcmp(astat.status.adapter_address, kWLA_MAC, 6) == 0);
357 #define NETBIOS_NAME_FULL 0
358 #define NETBIOS_NAME_SUFFIX 1
359 #define AFSCONFIGKEYNAME TEXT("SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters")
361 void GetUncServerName(int lanaNumber, BOOL isGateway, TCHAR* name, int type)
363 lana_number_t lana = LANA_INVALID;
366 char cm_HostName[MAX_PATH];
367 TCHAR tmpName[MAX_PATH];
369 memset(msg, 0, sizeof(msg));
370 memset(tmpName, 0, sizeof(tmpName));
371 memset(cm_HostName, 0, sizeof(cm_HostName));
372 WSAStartup(0x0101, &WSAjunk);
374 if (lanaNumber == -1) {
375 /* Find the default LAN adapter to use. First look for
376 * the adapter named AFS; otherwise, unless we are doing
377 * gateway service, look for any valid loopback adapter.
379 lanainfo = GetLana(msg, "AFS");
382 lana = lanainfo[0].lana_number;
385 if (lana == LANA_INVALID && !isGateway)
386 lana = lana_FindLoopback(msg);
387 if (lana != LANA_INVALID)
390 /* If we are using a loopback adapter, we can use the preferred
391 * (but non-unique) server name; otherwise, we must fall back to
392 * the <machine>-AFS name.
394 if (lanaNumber >= 0 && lana_IsLoopback(lanaNumber, msg))
397 char mountRoot[MAX_PATH+1];
398 char *pmount=mountRoot;
399 DWORD len=sizeof(mountRoot)-1;
400 printf("int mountroot \n");
401 if ((RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSCONFIGKEYNAME,0, KEY_QUERY_VALUE, &parmKey)!= ERROR_SUCCESS)
402 || (RegQueryValueEx(parmKey, "Mountroot", NULL, NULL,(LPBYTE)(mountRoot), &len)!= ERROR_SUCCESS)
403 || (len > sizeof(mountRoot)-1)
405 strcpy(mountRoot, "afs");
406 RegCloseKey(parmKey);
407 mountRoot[len]=0; /*safety see ms-help://MS.MSDNQTR.2002OCT.1033/sysinfo/base/regqueryvalueex.htm*/
408 if ((*pmount=='/') || (*pmount='\\'))
411 _tcscpy(name, pmount);
413 gethostname(cm_HostName, sizeof(cm_HostName));
414 _tcscpy(tmpName, cm_HostName);
415 char* ctemp = _tcschr(tmpName, '.'); /* turn ntdfs.* into ntdfs */
416 if (ctemp) *ctemp = 0;
417 tmpName[11] = 0; /* ensure that even after adding the -A, we
418 * leave one byte free for the netbios server
421 if (type == NETBIOS_NAME_FULL) {
422 _tcscat(tmpName, _T("-afs"));
423 _tcscpy(name, tmpName);
425 _tcscpy(name, _T("-afs"));
430 void GetAfsName(int lanaNumber, BOOL isGateway, TCHAR* name)
433 GetUncServerName(lanaNumber, isGateway, name, NETBIOS_NAME_FULL);
434 _stprintf(name, _T("Your UNC name to reach the root of AFS is \\\\%s\\all"), name);