d704adac67090f1d2594ca351c9a94ef4342a8b5
[openafs.git] / src / WINNT / afsd / lanahelper.cpp
1 /*
2
3 Copyright 2004 by the Massachusetts Institute of Technology
4
5 All rights reserved.
6
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the name of the Massachusetts
12 Institute of Technology (M.I.T.) not be used in advertising or publicity
13 pertaining to distribution of the software without specific, written
14 prior permission.
15
16 M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
17 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
18 M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
19 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
22 SOFTWARE.
23
24 */
25
26 #include <windows.h>
27 #include <winreg.h>
28 #include <nb30.h>
29 #include <tchar.h>
30 #include <shellapi.h>
31 #include <objbase.h>
32 #include <shlobj.h>
33 #include <wtypes.h>
34 #include <string.h>
35 #include <malloc.h>
36 #include <stdio.h>
37 #include <lanahelper.h>
38
39 #define NOLOGGING
40 #ifndef NOLOGGING
41 extern "C" {
42 #include <stdarg.h>
43
44     void afsi_log(TCHAR *p, ...) {
45         va_list marker;
46         TCHAR buffer[200];
47
48         va_start(marker,p);
49         _vstprintf(buffer,p,marker);
50         va_end(marker);
51         _tcscat(buffer,_T("\n"));
52
53         OutputDebugString(buffer);
54     }
55 }
56 #endif
57
58 static const char *szAFSConfigKeyName = "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters";
59 static const char *szNetbiosNameValue = "NetbiosName";
60 static const char *szIsGatewayValue = "IsGateway";
61 static const char *szLanAdapterValue = "LanAdapter";
62 static const char *szNoFindLanaByName = "NoFindLanaByName";
63
64 // Use the IShellFolder API to get the connection name for the given Guid.
65 static HRESULT lana_ShellGetNameFromGuidW(WCHAR *wGuid, WCHAR *wName, int NameSize)
66 {
67     // This is the GUID for the network connections folder. It is constant.
68     // {7007ACC7-3202-11D1-AAD2-00805FC1270E}
69     const GUID CLSID_NetworkConnections = {
70         0x7007ACC7, 0x3202, 0x11D1, {
71             0xAA, 0xD2, 0x00, 0x80, 0x5F, 0xC1, 0x27, 0x0E
72         }
73     };
74     LPITEMIDLIST pidl;
75     IShellFolder *pShellFolder;
76     IMalloc *pShellMalloc;
77
78     // Build the display name in the form "::{GUID}".
79     if (wcslen(wGuid) >= MAX_PATH)
80         return E_INVALIDARG;
81     WCHAR szAdapterGuid[MAX_PATH + 2];
82     swprintf(szAdapterGuid, L"::%ls", wGuid);
83
84     // Initialize COM.
85     CoInitialize(NULL);
86
87     // Get the shell allocator.
88     HRESULT hr = SHGetMalloc(&pShellMalloc);
89     if (SUCCEEDED(hr))
90     {
91         // Create an instance of the network connections folder.
92         hr = CoCreateInstance(CLSID_NetworkConnections, NULL,
93                               CLSCTX_INPROC_SERVER, IID_IShellFolder,
94                               reinterpret_cast<LPVOID *>(&pShellFolder));
95     }
96     if (SUCCEEDED(hr)) 
97     {
98         hr = pShellFolder->ParseDisplayName(NULL, NULL, szAdapterGuid, NULL,
99                                             &pidl, NULL);
100     }
101     if (SUCCEEDED(hr)) {
102         // Get the display name; this returns the friendly name.
103         STRRET sName;
104         hr = pShellFolder->GetDisplayNameOf(pidl, SHGDN_NORMAL, &sName);
105         if (SUCCEEDED(hr))
106             wcsncpy(wName, sName.pOleStr, NameSize);
107         pShellMalloc->Free(pidl);
108     }
109
110     CoUninitialize();
111     return hr;
112 }
113
114 // Get the Connection Name for the given GUID.
115 extern "C" int lana_GetNameFromGuid(char *Guid, char **Name)
116 {
117     typedef HRESULT (WINAPI *HrLanProcAddr)(GUID *, PCWSTR, PWSTR, LPDWORD);
118     HrLanProcAddr HrLanProc = NULL;
119     HMODULE hNetMan;
120     int size;
121     WCHAR *wGuid = NULL;
122     WCHAR wName[MAX_PATH];
123     DWORD NameSize = MAX_PATH;
124     char *name = NULL;
125     HRESULT status;
126         
127     // Convert the Guid string to Unicode.  First we ask only for the size
128     // of the converted string.  Then we allocate a buffer of sufficient
129     // size to hold the result of the conversion.
130     size = MultiByteToWideChar(CP_ACP, 0, Guid, -1, NULL, 0);
131     wGuid = (WCHAR *) malloc(size * sizeof(WCHAR));
132     MultiByteToWideChar(CP_ACP, 0, Guid, -1, wGuid, size);
133
134     // First try the IShellFolder interface, which was unimplemented
135     // for the network connections folder before XP.
136
137     /* XXX pbh 9/11/03 - revert to using the undocumented APIs on XP while
138      *   waiting to hear back from PSS about the slow reboot issue.
139      *   This is an ugly, misleading hack, but is minimally invasive
140      *   and will be easy to rollback.
141      */
142
143     //status = getname_shellfolder(wGuid, wName, NameSize);
144     status = E_NOTIMPL;
145
146     /* XXX end of pbh 9/11/03 temporary hack*/  
147
148     if (status == E_NOTIMPL) {
149         // The IShellFolder interface is not implemented on this platform.
150         // Try the (undocumented) HrLanConnectionNameFromGuidOrPath API
151         // from the netman DLL.
152 #ifndef NOLOGGING
153         afsi_log("IShellFolder API not implemented, trying HrLanConnectionNameFromGuidOrPath");
154 #endif
155         hNetMan = LoadLibrary("netman.dll");
156         if (hNetMan == NULL) {
157             free(wGuid);
158             return -1;
159         }
160         /* Super Secret Microsoft Call */
161         HrLanProc = (HrLanProcAddr) GetProcAddress(hNetMan,
162                                                    "HrLanConnectionNameFromGuidOrPath");
163         if (HrLanProc == NULL) {
164             FreeLibrary(hNetMan);
165             free(wGuid);
166             return -1;
167         }
168         status = HrLanProc(NULL, wGuid, wName, &NameSize);
169         FreeLibrary(hNetMan);
170     }
171     free(wGuid);
172     if (FAILED(status)) {
173 #ifndef NOLOGGING
174         afsi_log("lana_GetNameFromGuid: failed to get connection name (status %ld)",
175                  status);
176 #endif
177         return -1;
178     }
179
180     // Get the required buffer size, and then convert the string.
181     size = WideCharToMultiByte(CP_ACP, 0, wName, -1, NULL, 0, NULL, NULL);
182     name = (char *) malloc(size);
183     if (name == NULL)
184         return -1;
185     WideCharToMultiByte(CP_ACP, 0, wName, -1, name, size, NULL, NULL);
186 #ifndef NOLOGGING
187     afsi_log("Connection name for %s is '%s'", Guid, name);
188 #endif
189     if (*Name)
190         *Name = name;
191     else
192         free(name);
193     return 0;
194 }
195
196 // Return an array of LANAINFOs corresponding to a connection named LanaName
197 // (NULL LanaName matches all connections), and has an IPv4 binding. Returns
198 // NULL if something goes wrong.
199 // NOTE: caller must free the returned block if non NULL.
200 extern "C" LANAINFO * lana_FindLanaByName(const char *LanaName)
201 {
202     const char RegNetBiosLinkageKeyName[] =
203         "System\\CurrentControlSet\\Services\\NetBios\\Linkage";
204     HKEY hkey;
205     LONG status;
206     struct {
207         BYTE flags;
208         BYTE number;
209     } lanamap[MAX_LANA+1];
210     DWORD lanamapsize = sizeof(lanamap);
211     DWORD type;
212     char *bindpaths = NULL;
213     DWORD bindpathsize;
214     int nlana;
215     int i;
216     char *guid;
217     char *name;
218     char *pBind;
219     char *p;
220
221     LANAINFO * lanainfo;
222
223     // Open the NetBios Linkage key.
224     status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, RegNetBiosLinkageKeyName, 0, 
225                           KEY_QUERY_VALUE, &hkey);
226         
227     if (status != ERROR_SUCCESS) {
228 #ifndef NOLOGGING
229         afsi_log("Failed to open NetBios Linkage key (status %ld)", status);
230 #endif
231         return NULL;
232     }
233
234     // Read the lana map.
235     status = RegQueryValueEx(hkey, "LanaMap", 0, &type,
236                          (BYTE *) &lanamap, &lanamapsize);
237     if (status != ERROR_SUCCESS) {
238 #ifndef NOLOGGING
239         afsi_log("Failed to read LanaMap (status %ld)", status);
240 #endif
241         RegCloseKey(hkey);
242         return NULL;
243     }
244     if (lanamapsize == 0) {
245 #ifndef NOLOGGING
246         afsi_log("No data in LanaMap");
247 #endif
248         return NULL;
249     }
250     nlana = lanamapsize / sizeof(lanamap[0]);
251
252     // Get the bind paths for NetBios so we can match them up
253     // with the lana map.  First we query for the size, so we
254     // can allocate an appropriate buffer.
255     status = RegQueryValueEx(hkey, "Bind", 0, &type, NULL, &bindpathsize);
256     if (status == ERROR_SUCCESS && bindpathsize != 0) {
257         bindpaths = (char *) malloc(bindpathsize * sizeof(char));
258         if (bindpaths == NULL) {
259 #ifndef NOLOGGING
260             afsi_log("Cannot allocate %ld bytes for bindpaths", bindpathsize);
261 #endif
262             RegCloseKey(hkey);
263             return NULL;
264         }
265         status = RegQueryValueEx(hkey, "Bind", 0, &type, 
266                                  (BYTE *) bindpaths, &bindpathsize);
267     }
268     RegCloseKey(hkey);
269     if (status != ERROR_SUCCESS) {
270 #ifndef NOLOGGING
271         afsi_log("Failed to read bind paths (status %ld)", status);
272 #endif
273         if (bindpaths != NULL)
274             free(bindpaths);
275         return NULL;
276       }
277     if (bindpathsize == 0) {
278 #ifndef NOLOGGING
279         afsi_log("No bindpath data");
280 #endif
281         if (bindpaths != NULL)
282             free(bindpaths);
283         return NULL;
284     }
285
286     if (LanaName)
287     {
288         lanainfo = (LANAINFO *) malloc(sizeof(LANAINFO)*2);
289         if(lanainfo == NULL) {
290             free(bindpaths);
291             return NULL;
292         }
293         memset(lanainfo, 0, sizeof(LANAINFO) * 2);
294         lanainfo[0].lana_number = LANA_INVALID;
295     }
296     else
297     {
298         lanainfo = (LANAINFO *) malloc(sizeof(LANAINFO)*(nlana+1));
299         if(lanainfo == NULL) {
300             free(bindpaths);
301             return NULL;
302         }
303         memset(lanainfo, 0, sizeof(LANAINFO) * (nlana+1));
304     }
305     
306     int index = 0;
307
308     // Iterate over the lana map entries and bind paths.
309     for (i = 0, pBind = bindpaths; i < nlana;
310          i++, pBind += strlen(pBind) + 1) {
311         // Ignore an invalid map entry.
312         if ((lanamap[i].flags & 1) == 0)
313             continue;
314
315                 // check for an IPv4 binding
316                 if(!strstr(pBind,"_Tcpip_"))
317                         continue;
318
319         // Find the beginning of the GUID.
320         guid = strchr(pBind, '{');
321         if (guid == NULL)
322             continue;                   // Malformed path entry?
323         guid = strdup(guid);
324         if (guid == NULL)
325             continue;
326         // Find the end of the GUID.
327         p = strchr(guid, '}');
328         if (p == NULL) {
329             free(guid);                 // Malformed GUID?
330             continue;
331         }
332         *++p = '\0';                    // Ignore anything after the GUID.
333         status = lana_GetNameFromGuid(guid, &name);
334         free(guid);
335
336         if (status == 0 && name != 0)
337         {
338             if (LanaName)
339             {
340                 if (strcmp(name, LanaName) ==0)
341                 {
342                     lanainfo[index].lana_number = lanamap[i].number;
343                     _tcscpy(lanainfo[index].lana_name, name);
344                     free(name);
345                     index++;
346                     break;
347                 }
348             }
349             else
350             {
351                 lanainfo[index].lana_number = lanamap[i].number;
352                 _tcscpy(lanainfo[index].lana_name, name);
353                 free(name);
354                 index++;
355             }
356         }
357     }
358
359     lanainfo[index].lana_number = LANA_INVALID;
360
361     free(bindpaths);
362     return lanainfo;
363 }
364
365 extern "C" lana_number_t lana_FindLoopback(void)
366 {
367     NCB ncb;
368     LANA_ENUM lana_list;
369     int status;
370     int i;
371
372     memset(&ncb, 0, sizeof(ncb));
373     ncb.ncb_command = NCBENUM;
374     ncb.ncb_buffer = (UCHAR *) &lana_list;
375     ncb.ncb_length = sizeof(lana_list);
376     status = Netbios(&ncb);
377     if (status != 0) {
378 #ifndef NOLOGGING
379         afsi_log("Netbios NCBENUM failed: status %ld", status);
380 #endif
381         return LANA_INVALID;
382     }
383     for (i = 0; i < lana_list.length; i++) {
384         if (lana_IsLoopback(lana_list.lana[i])) {
385             // Found one, return it.
386 #ifndef NOLOGGING
387             afsi_log("lana_FindLoopback: Found LAN adapter %d",
388                      lana_list.lana[i]);
389 #endif
390             return lana_list.lana[i];
391         }
392     }
393     // Could not find a loopback adapter.
394     return LANA_INVALID;
395 }
396
397 // Is the given lana a Windows Loopback Adapter?
398 // TODO: implement a better check for loopback
399 // TODO: also check for proper bindings (IPv4)
400 extern "C" BOOL lana_IsLoopback(lana_number_t lana)
401 {
402     NCB ncb;
403     struct {
404         ADAPTER_STATUS status;
405         NAME_BUFFER names[MAX_LANA+1];
406     } astat;
407     unsigned char kWLA_MAC[6] = { 0x02, 0x00, 0x4c, 0x4f, 0x4f, 0x50 };
408     int status;
409
410     // Reset the adapter: in Win32, this is required for every process, and
411     // acts as an init call, not as a real hardware reset.
412     memset(&ncb, 0, sizeof(ncb));
413     ncb.ncb_command = NCBRESET;
414     ncb.ncb_callname[0] = 100;
415     ncb.ncb_callname[2] = 100;
416     ncb.ncb_lana_num = lana;
417     status = Netbios(&ncb);
418     if (status == 0)
419         status = ncb.ncb_retcode;
420     if (status != 0) {
421 #ifndef NOLOGGING
422        afsi_log("NCBRESET failed: lana %u, status %ld", lana, status);
423 #endif
424         return FALSE;
425     }
426
427     // Use the NCBASTAT command to get the adapter address.
428     memset(&ncb, 0, sizeof(ncb));
429     ncb.ncb_command = NCBASTAT;
430     ncb.ncb_lana_num = lana;
431     strcpy((char *) ncb.ncb_callname, "*               ");
432     ncb.ncb_buffer = (UCHAR *) &astat;
433     ncb.ncb_length = sizeof(astat);
434     status = Netbios(&ncb);
435     if (status == 0)
436         status = ncb.ncb_retcode;
437     if (ncb.ncb_retcode != 0) {
438 #ifndef NOLOGGING   
439         afsi_log("NCBASTAT failed: lana %u, status %ld", lana, status);
440 #endif
441         return FALSE;
442     }
443     return (memcmp(astat.status.adapter_address, kWLA_MAC, 6) == 0);
444 }
445
446 // Get the netbios named used/to-be-used by the AFS SMB server.
447 // IF <lana specified> THEN
448 //     Use specified lana
449 // ELSE
450 //         Look for an adapter named "AFS", failing which,
451 //     look for a loopback adapter.
452 // ENDIF
453 // IF lana is for a loopback && !IsGateway THEN
454 //    IF netbios name is specified THEN
455 //       use specified netbios name
456 //    ELSE
457 //       use "AFS"
458 //    ENDIF
459 // ELSE
460 //    use netbios name "<hostname>-AFS"
461 // ENDIF
462 // Return ERROR_SUCCESS if netbios name was successfully generated.
463 // Returns the lana number to use in *pLana (if pLana is non-NULL) and also
464 //         the IsGateway setting in *pIsGateway (if pIsGateway is non-NULL).
465 //         the type of name returned.
466 //
467 // buffer is assumed to hold at least MAX_NB_NAME_LENGTH bytes.
468 //
469 // flags :
470 //        LANA_NETBIOS_NAME_IN : Use the values of *pLana and *pIsGateway as [in] parameters.
471 //        LANA_NETBIOS_NAME_SUFFIX : Only return the suffix of netbios name
472 //                LANA_NETBIOS_NAME_FULL : Return full netbios name
473 extern "C" long lana_GetUncServerNameEx(char *buffer, lana_number_t * pLana, int * pIsGateway, int flags) {
474     HKEY hkConfig;
475         DWORD dummyLen;
476         LONG rv;
477         int regLana;
478         int regGateway, regNoFindLanaByName;
479         TCHAR regNbName[MAX_NB_NAME_LENGTH];
480         TCHAR nbName[MAX_NB_NAME_LENGTH];
481         TCHAR hostname[MAX_COMPUTERNAME_LENGTH+1];
482
483         rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,szAFSConfigKeyName,0,KEY_READ,&hkConfig);
484         if(rv == ERROR_SUCCESS) {
485                 if(!(flags & LANA_NETBIOS_NAME_IN) || !pLana) {
486                         dummyLen = sizeof(regLana);
487                         rv = RegQueryValueEx(hkConfig, szLanAdapterValue, NULL, NULL, (LPBYTE) &regLana, &dummyLen);
488                         if(rv != ERROR_SUCCESS) regLana = -1;
489                 } else
490                         regLana = *pLana;
491
492                 if(!(flags & LANA_NETBIOS_NAME_IN) || !pIsGateway) {
493                         dummyLen = sizeof(regGateway);
494                         rv = RegQueryValueEx(hkConfig, szIsGatewayValue, NULL, NULL, (LPBYTE) &regGateway, &dummyLen);
495                         if(rv != ERROR_SUCCESS) regGateway = 0;
496                 } else
497                         regGateway = *pIsGateway;
498
499                 dummyLen = sizeof(regNoFindLanaByName);
500                 rv = RegQueryValueEx(hkConfig, szNoFindLanaByName, NULL, NULL, (LPBYTE) &regNoFindLanaByName, &dummyLen);
501                 if(rv != ERROR_SUCCESS) regNoFindLanaByName = 0;
502
503                 // Do not care if the call fails for insufficient buffer size.  We are not interested
504                 // in netbios names over 15 chars.
505                 dummyLen = sizeof(regNbName);
506                 rv = RegQueryValueEx(hkConfig, szNetbiosNameValue, NULL, NULL, (LPBYTE) &regNbName, &dummyLen);
507                 if(rv != ERROR_SUCCESS) regNbName[0] = 0;
508                 else regNbName[15] = 0;
509
510                 RegCloseKey(hkConfig);
511         } else {
512                 if(flags & LANA_NETBIOS_NAME_IN) {
513                         regLana = (pLana)? *pLana: -1;
514                         regGateway = (pIsGateway)? *pIsGateway: 0;
515                 } else {
516                         regLana = -1;
517                         regGateway = 0;
518                 }
519         regNoFindLanaByName = 0;
520                 regNbName[0] = 0;
521         }
522
523     if(regLana < 0 || regLana > MAX_LANA) 
524         regLana = -1;
525
526         if(regLana == -1) {
527                 LANAINFO *lanaInfo = NULL;
528         int nLana = LANA_INVALID;
529
530         if (!regNoFindLanaByName)
531             lanaInfo = lana_FindLanaByName("AFS");
532                 if(lanaInfo != NULL) {
533             nLana = lanaInfo[0].lana_number;
534                         free(lanaInfo);
535                 } else
536                         nLana = LANA_INVALID;
537
538                 if(nLana == LANA_INVALID && !regGateway) {
539                         nLana = lana_FindLoopback();
540                 }
541                 if(nLana != LANA_INVALID) 
542             regLana = nLana;
543         }
544
545         if(regNbName[0] &&
546        (regLana >=0 && lana_IsLoopback((lana_number_t) regLana))) {
547         strncpy(nbName,regNbName,15);
548         nbName[16] = 0;
549         strupr(nbName);
550         } else {
551                 char * dot;
552
553                 if(flags & LANA_NETBIOS_NAME_SUFFIX) {
554                         strcpy(nbName,"-AFS");
555                 } else {
556                         dummyLen = sizeof(hostname);
557                         // assume we are not a cluster.
558                         rv = GetComputerName(hostname, &dummyLen);
559                         if(!SUCCEEDED(rv)) { // should not happen, but...
560                                 return rv;
561                         }
562                         strncpy(nbName, hostname, 11);
563                         nbName[11] = 0;
564                         if(dot = strchr(nbName,'.'))
565                                 *dot = 0;
566                         strcat(nbName,"-AFS");
567                 }
568         }
569
570         if(pLana) *pLana = regLana;
571         if(pIsGateway) *pIsGateway = regGateway;
572
573         strcpy(buffer, nbName);
574
575         return ERROR_SUCCESS;
576 }
577
578 extern "C" void lana_GetUncServerNameDynamic(int lanaNumber, BOOL isGateway, TCHAR *name, int type) {
579         char szName[MAX_NB_NAME_LENGTH];
580         lana_number_t lana = (lana_number_t) lanaNumber;
581         int gateway = (int) isGateway;
582
583         if(SUCCEEDED(lana_GetUncServerNameEx(szName, &lana, &gateway, LANA_NETBIOS_NAME_IN | type))) {
584 #ifdef _UNICODE
585                 mbswcs(name,szName,MAX_NB_NAME_LENGTH);
586 #else
587                 strncpy(name,szName,MAX_NB_NAME_LENGTH);
588 #endif
589         } else
590                 *name = _T('\0');
591 }
592
593 extern "C" void lana_GetUncServerName(TCHAR *name, int type) {
594         char szName[MAX_NB_NAME_LENGTH];
595
596         if(SUCCEEDED(lana_GetUncServerNameEx(szName,NULL,NULL,type))) {
597 #ifdef _UNICODE
598                 mbswcs(name,szName,MAX_NB_NAME_LENGTH);
599 #else
600                 strncpy(name,szName,MAX_NB_NAME_LENGTH);
601 #endif
602         } else {
603         *name = _T('\0');
604         }
605 }
606
607 extern "C" void lana_GetAfsNameString(int lanaNumber, BOOL isGateway, TCHAR* name)
608 {
609     TCHAR netbiosName[32];
610     lana_GetUncServerNameDynamic(lanaNumber, isGateway, netbiosName, LANA_NETBIOS_NAME_FULL);
611     _stprintf(name, _T("Your UNC name to reach the root of AFS is \\\\%s\\all"), netbiosName);
612 }
613
614 extern "C" void lana_GetNetbiosName(LPTSTR pszName, int type)
615 {
616         HKEY hkCfg;
617     TCHAR name[MAX_NB_NAME_LENGTH];
618         DWORD dummyLen;
619
620     memset(name, 0, sizeof(name));
621     if (GetVersion() >= 0x80000000) // not WindowsNT
622     {
623         if (type == LANA_NETBIOS_NAME_SUFFIX)
624         {
625             _tcscpy(pszName, TEXT("-afs"));
626             return;
627         }
628
629                 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,szAFSConfigKeyName,0,KEY_READ,&hkCfg) == ERROR_SUCCESS) {
630                         dummyLen = sizeof(name);
631                         if(RegQueryValueEx(hkCfg,TEXT("Gateway"),NULL,NULL,(LPBYTE) name,&dummyLen) == ERROR_SUCCESS)
632                                 name[0] = _T('\0');
633                         RegCloseKey(hkCfg);
634                 }
635
636         if (_tcslen(name) == 0)
637         {
638             _tcscpy(pszName, TEXT("unknown"));
639             return;
640         }
641
642                 _tcscpy(pszName, name);
643         _tcscat(pszName, TEXT("-afs"));
644         return;
645     }
646
647     lana_GetUncServerName(name,type);
648         _tcslwr(name);
649     _tcscpy(pszName, name);
650     return;
651 }
652