summaryrefslogtreecommitdiffstats
path: root/private/nw/svcdlls/nwwks/client/nwshui.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'private/nw/svcdlls/nwwks/client/nwshui.cxx')
-rw-r--r--private/nw/svcdlls/nwwks/client/nwshui.cxx1630
1 files changed, 1630 insertions, 0 deletions
diff --git a/private/nw/svcdlls/nwwks/client/nwshui.cxx b/private/nw/svcdlls/nwwks/client/nwshui.cxx
new file mode 100644
index 000000000..48dea8f96
--- /dev/null
+++ b/private/nw/svcdlls/nwwks/client/nwshui.cxx
@@ -0,0 +1,1630 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ nwshui.cxx
+
+Abstract:
+
+ This module implements the context menu actions of shell extension classes.
+
+Author:
+
+ Yi-Hsin Sung (yihsins) 25-Oct-1995
+
+--*/
+
+extern "C"
+{
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <commctrl.h>
+#include <shellapi.h>
+#include <shlobj.h>
+#define DONT_WANT_SHELLDEBUG
+#include <shsemip.h>
+#include <winnetwk.h>
+#include <npapi.h>
+#include <ntddnwfs.h>
+#include <ndsapi32.h>
+#include <nwapi.h>
+#include <nwwks.h>
+#include <nwmisc.h>
+#include "nwutil.h"
+}
+
+#include "nwshcmn.h"
+#include "nwshrc.h"
+
+extern "C"
+{
+NTSTATUS
+NwNdsOpenRdrHandle(
+ OUT PHANDLE phandleRdr );
+}
+
+#define MAX_ONE_CONN_INFORMATION_SIZE 512
+#define NW_ENUM_EXTRA_BYTES 256
+#define GLOBAL_WHOAMI_REFRESH_INTERVAL 30000 // in milliseconds, Win95 uses 10000
+
+DWORD
+LogoutFromServer(
+ LPWSTR pszServer,
+ PBOOL pfDisconnected
+);
+
+BOOL
+CALLBACK
+GlobalWhoAmIDlgProc(
+ HWND hwndDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam );
+
+VOID
+GetConnectionStatusString(
+ PCONN_STATUS pConnStatus,
+ LPBYTE Buffer,
+ DWORD nSize
+);
+
+HRESULT
+NWUIWhoAmI(
+ HWND hParent,
+ LPNETRESOURCE pNetRes
+)
+{
+ DWORD err = NO_ERROR;
+ DWORD ResumeKey = 0;
+ LPBYTE pBuffer = NULL;
+ DWORD EntriesRead = 0;
+ DWORD dwMessageId;
+ WCHAR szUserName[MAX_PATH+1] = L"";
+ WCHAR szConnType[128];
+ WCHAR szRemoteName[MAX_PATH + 1];
+
+ szConnType[0] = 0;
+
+ if ( pNetRes->dwDisplayType == RESOURCEDISPLAYTYPE_SERVER )
+ {
+ // Need to extract the server name from full UNC path
+ NwExtractServerName( pNetRes->lpRemoteName, szRemoteName );
+ dwMessageId = IDS_MESSAGE_NOT_ATTACHED;
+ }
+ else // NDS container name
+ {
+ // Need to extract the tree name from the full UNC path
+ szRemoteName[0] = TREECHAR;
+ NwExtractTreeName( pNetRes->lpRemoteName, szRemoteName+1);
+ dwMessageId = IDS_MESSAGE_NOT_ATTACHED_TO_TREE;
+ }
+
+ err = NwGetConnectionStatus( szRemoteName,
+ &ResumeKey,
+ &pBuffer,
+ &EntriesRead );
+
+ if ( err == NO_ERROR && EntriesRead > 0 )
+ // For trees, we'll get more than one entry
+ {
+ PCONN_STATUS pConnStatus = (PCONN_STATUS) pBuffer;
+ LPWSTR pszStart = szConnType;
+ DWORD nSize = sizeof(szConnType)/sizeof(WCHAR);
+
+ if ( EntriesRead > 1 && szRemoteName[0] == TREECHAR )
+ {
+ // If there is more than one entry for trees,
+ // then we need to find one entry where username is not null
+ // and the login type is NDS.
+ // If we cannot find one, then just use the first one.
+
+ DWORD i;
+ PCONN_STATUS pConnStatusTmp = pConnStatus;
+ PCONN_STATUS pConnStatusUser = NULL;
+ PCONN_STATUS pConnStatusNoUser = NULL;
+
+ for ( i = 0; i < EntriesRead ; i++ )
+ {
+ if ( pConnStatusTmp->fNds )
+ {
+ pConnStatusNoUser = pConnStatusTmp;
+
+ if ( ( pConnStatusTmp->pszUserName != NULL )
+ && ( ( pConnStatusTmp->dwConnType == NW_CONN_NDS_AUTHENTICATED_NO_LICENSE )
+ || ( pConnStatusTmp->dwConnType == NW_CONN_NDS_AUTHENTICATED_LICENSED )
+ )
+ )
+ {
+ // Found it
+ pConnStatusUser = pConnStatusTmp;
+ break;
+ }
+ }
+
+ // Continue with the next item
+ pConnStatusTmp = (PCONN_STATUS) ( (DWORD) pConnStatusTmp
+ + pConnStatusTmp->dwTotalLength);
+ }
+
+ if ( pConnStatusUser ) // found one nds entry with a user name
+ pConnStatus = pConnStatusUser;
+ else if ( pConnStatusNoUser ) // use an nds entry with no user name
+ pConnStatus = pConnStatusNoUser;
+ // else use the first entry
+
+ }
+
+ if ( szRemoteName[0] == TREECHAR // A tree
+ || !pConnStatus->fPreferred // A server but not preferred
+ )
+ {
+ // Show this conneciton only if this is a tree or if this is
+ // not a implicit connection to the preferred server.
+
+ dwMessageId = pNetRes->dwDisplayType == RESOURCEDISPLAYTYPE_SERVER ?
+ IDS_MESSAGE_ATTACHED : IDS_MESSAGE_ATTACHED_TO_TREE;
+
+ if ( pConnStatus->pszUserName )
+ {
+ wcscpy( szUserName, pConnStatus->pszUserName );
+ }
+
+ if ( pConnStatus->fNds ) // NDS
+ {
+ LoadString( ::hmodNW, IDS_LOGIN_TYPE_NDS, pszStart, nSize );
+ nSize -= wcslen( pszStart );
+ pszStart += wcslen( pszStart);
+
+ }
+ else // Bindery
+ {
+ LoadString( ::hmodNW, IDS_LOGIN_TYPE_BINDERY, pszStart, nSize );
+ nSize -= wcslen( pszStart );
+ pszStart += wcslen( pszStart);
+ }
+
+ LoadString( ::hmodNW, IDS_LOGIN_STATUS_SEPARATOR, pszStart, nSize );
+ nSize -= wcslen( pszStart );
+ pszStart += wcslen( pszStart);
+
+ GetConnectionStatusString( pConnStatus, (LPBYTE) pszStart, nSize );
+ }
+ }
+
+ if ( err == NO_ERROR )
+ {
+ // Popup the message now.
+ ::MsgBoxPrintf( hParent,
+ dwMessageId,
+ IDS_TITLE_WHOAMI,
+ MB_OK | MB_SETFOREGROUND | MB_ICONINFORMATION,
+ szRemoteName[0] == TREECHAR? szRemoteName + 1 : szRemoteName,
+ szUserName,
+ szConnType );
+ }
+ else // error occurred
+ {
+ ::MsgBoxErrorPrintf( hParent,
+ IDS_MESSAGE_CONNINFO_ERROR,
+ IDS_TITLE_WHOAMI,
+ MB_OK | MB_SETFOREGROUND | MB_ICONSTOP,
+ err,
+ NULL );
+ }
+
+ if ( pBuffer != NULL )
+ {
+ LocalFree( pBuffer );
+ pBuffer = NULL;
+ }
+
+ return NOERROR;
+}
+
+VOID
+GetConnectionStatusString(
+ PCONN_STATUS pConnStatus,
+ LPBYTE Buffer,
+ DWORD nSize
+)
+{
+ LPWSTR pszStart = (LPWSTR) Buffer;
+ DWORD dwMessageId = 0;
+
+ if ( pConnStatus->fNds ) // NDS
+ {
+ if ( pConnStatus->dwConnType == NW_CONN_NOT_AUTHENTICATED )
+ {
+ dwMessageId = IDS_LOGIN_STATUS_NOT_AUTHENTICATED;
+ }
+ else if ( pConnStatus->dwConnType == NW_CONN_DISCONNECTED )
+ {
+ dwMessageId = IDS_LOGIN_STATUS_NOT_ATTACHED;
+ }
+ else // authenticated, licensed or unlicensed
+ {
+ LoadString( ::hmodNW, IDS_LOGIN_STATUS_AUTHENTICATED,
+ pszStart, nSize );
+ nSize -= wcslen( pszStart );
+ pszStart += wcslen( pszStart);
+
+ if ( pConnStatus->dwConnType == NW_CONN_NDS_AUTHENTICATED_LICENSED )
+ dwMessageId = IDS_LOGIN_STATUS_LICENSED;
+ else // NW_CONN_NDS_AUTHENTICATED_NO_LICENSE
+ dwMessageId = IDS_LOGIN_STATUS_NOT_LICENSED;
+ }
+ }
+ else // Bindery
+ {
+ if ( pConnStatus->dwConnType == NW_CONN_BINDERY_LOGIN )
+ dwMessageId = IDS_LOGIN_STATUS_LOGGED_IN;
+ else if ( pConnStatus->dwConnType == NW_CONN_DISCONNECTED )
+ dwMessageId = IDS_LOGIN_STATUS_NOT_ATTACHED;
+ else
+ dwMessageId = IDS_LOGIN_STATUS_ATTACHED_ONLY;
+ }
+
+ LoadString( ::hmodNW, dwMessageId, pszStart, nSize );
+}
+
+HRESULT
+NWUIGlobalWhoAmI(
+ HWND hParent
+)
+{
+ ::DialogBoxParam( ::hmodNW,
+ MAKEINTRESOURCE(DLG_GLOBAL_WHOAMI),
+ hParent,
+ (DLGPROC) ::GlobalWhoAmIDlgProc,
+ NULL );
+
+ return NOERROR;
+}
+
+HRESULT
+NWUILogOut(
+ HWND hParent,
+ LPNETRESOURCE pNetRes,
+ PBOOL pfDisconnected
+)
+{
+ DWORD err = NO_ERROR;
+ WCHAR szServer[MAX_PATH+1];
+ BOOL fAttached;
+ BOOL fAuthenticated;
+ DWORD dwMessageId;
+
+ *pfDisconnected = FALSE;
+
+ // Need to extract the server name from full UNC path
+ NwExtractServerName( pNetRes->lpRemoteName, szServer );
+
+ err = NwIsServerOrTreeAttached( szServer, &fAttached, &fAuthenticated );
+
+ if ( err == NO_ERROR && !fAttached )
+ {
+ dwMessageId = IDS_MESSAGE_NOT_ATTACHED;
+ }
+ else if ( err == NO_ERROR ) // attached
+ {
+ int nRet = ::MsgBoxPrintf( hParent,
+ IDS_MESSAGE_LOGOUT_CONFIRM,
+ IDS_TITLE_LOGOUT,
+ MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION);
+
+ if ( nRet != IDYES )
+ return NOERROR;
+
+ err = LogoutFromServer( szServer, pfDisconnected );
+
+ if ( err == NO_ERROR )
+ dwMessageId = IDS_MESSAGE_DETACHED;
+ else
+ dwMessageId = IDS_MESSAGE_LOGOUT_FAILED;
+ }
+ else // error occurred
+ {
+ ::MsgBoxErrorPrintf( hParent,
+ IDS_MESSAGE_CONNINFO_ERROR,
+ IDS_TITLE_LOGOUT,
+ MB_OK | MB_SETFOREGROUND | MB_ICONSTOP,
+ err,
+ NULL );
+
+ return NOERROR;
+ }
+
+ ::MsgBoxPrintf( hParent,
+ dwMessageId,
+ IDS_TITLE_LOGOUT,
+ MB_OK | MB_SETFOREGROUND | MB_ICONINFORMATION );
+
+ return NOERROR;
+}
+
+DWORD
+LogoutFromServer(
+ LPWSTR pszServer,
+ PBOOL pfDisconnected
+)
+{
+ DWORD err = NO_ERROR;
+ HANDLE EnumHandle = (HANDLE) NULL;
+
+ LPNETRESOURCE NetR = NULL;
+ LPNETRESOURCEW SavePtr;
+
+ DWORD BytesNeeded = MAX_ONE_NETRES_SIZE;
+ DWORD EntriesRead = 0;
+ DWORD i;
+
+ *pfDisconnected = FALSE;
+
+ err = NPOpenEnum( RESOURCE_CONNECTED,
+ 0,
+ 0,
+ NULL,
+ &EnumHandle );
+
+ if ( err != NO_ERROR)
+ {
+ EnumHandle = (HANDLE) NULL;
+ goto CleanExit;
+ }
+
+ //
+ // Allocate buffer to get server list.
+ //
+ if ((NetR = (LPNETRESOURCE) LocalAlloc( 0, BytesNeeded )) == NULL)
+ {
+ err = ERROR_NOT_ENOUGH_MEMORY;
+ goto CleanExit;
+ }
+
+ do {
+
+ EntriesRead = 0xFFFFFFFF; // Read as many as possible
+
+ err = NwEnumConnections( EnumHandle,
+ &EntriesRead,
+ (LPVOID) NetR,
+ &BytesNeeded,
+ TRUE );
+
+
+ if ( err == WN_SUCCESS)
+ {
+ SavePtr = NetR;
+
+ for (i = 0; i < EntriesRead; i++, NetR++)
+ {
+ BYTE Buffer[MAX_ONE_CONN_INFORMATION_SIZE];
+ BOOL fImplicit;
+ LPWSTR pszCurrentServer;
+
+ fImplicit = FALSE;
+
+ if ( NwIsNdsSyntax( NetR->lpRemoteName))
+ {
+ // For Nds name, the server name might not be in the full UNC name.
+ // Hence we need to get the server name from the Rdr.
+
+ DWORD err1 = NwGetConnectionInformation(
+ NetR->lpLocalName? NetR->lpLocalName : NetR->lpRemoteName,
+ Buffer,
+ sizeof(Buffer));
+
+ if ( err1 != NO_ERROR )
+ continue; // continue with the next entry if error occurred
+
+ pszCurrentServer = ((PCONN_INFORMATION) Buffer)->HostServer;
+
+ // Need to NULL terminate the server name, this will probably used the space
+ // occupied by UserName but since we are not using it, it is probably ok.
+ LPWSTR pszTemp = (LPWSTR) ((DWORD) pszCurrentServer
+ + ((PCONN_INFORMATION) Buffer)->HostServerLength );
+ *pszTemp = 0;
+
+ }
+ else // in the form \\server\sys
+ {
+ LPWSTR pszTemp;
+ wcscpy( (LPWSTR) Buffer, NetR->lpRemoteName + 2 ); // go past two backslashes
+
+ if ( pszTemp = wcschr( (LPWSTR) Buffer, L'\\' ))
+ *pszTemp = 0;
+ else
+ {
+ // The remote name contains only \\server, hence if the local name
+ // is null, this is a implicit connection
+ if ( NetR->lpLocalName == NULL )
+ fImplicit = TRUE;
+ }
+
+ pszCurrentServer = (LPWSTR) Buffer;
+ }
+
+
+ if ( _wcsicmp( pszCurrentServer, pszServer ) == 0 )
+ {
+
+ do {
+
+ // for implicit connections, we need to try and disconnect until
+ // we deleted all the implicit connections, i.e. until we
+ // get the invalid handle error
+
+ // NOTE: If we don't pass in CONNECT_UPDATE_PROFILE, shell won't update
+ // the windows that got disconnected. What do we want to do here?
+ err = WNetCancelConnection2(
+ NetR->lpLocalName? NetR->lpLocalName : NetR->lpRemoteName,
+ 0, // CONNECT_UPDATE_PROFILE,
+ TRUE );
+
+ if ( err == NO_ERROR )
+ *pfDisconnected = TRUE;
+
+ } while ( fImplicit && ( err == NO_ERROR));
+
+ if ( err == ERROR_INVALID_HANDLE )
+ {
+ // implicit connection will sometimes return this if the explicit connection
+ // is already disconnected
+ err = NO_ERROR;
+ }
+
+ if ( err != NO_ERROR )
+ {
+ NetR = SavePtr;
+ goto CleanExit;
+ }
+ }
+ }
+
+ NetR = SavePtr;
+ }
+ else if ( err != WN_NO_MORE_ENTRIES)
+ {
+ if ( err == WN_MORE_DATA)
+ {
+
+ //
+ // Original buffer was too small. Free it and allocate
+ // the recommended size and then some to get as many
+ // entries as possible.
+ //
+
+ (void) LocalFree((HLOCAL) NetR);
+
+ BytesNeeded += NW_ENUM_EXTRA_BYTES;
+
+ if ((NetR = (LPNETRESOURCE) LocalAlloc( 0, BytesNeeded )) == NULL)
+ {
+ err = ERROR_NOT_ENOUGH_MEMORY;
+ goto CleanExit;
+ }
+ }
+ else
+ {
+ goto CleanExit;
+ }
+ }
+
+ } while (err != WN_NO_MORE_ENTRIES);
+
+ if ( err == WN_NO_MORE_ENTRIES)
+ err = NO_ERROR;
+
+CleanExit:
+
+ if (EnumHandle != (HANDLE) NULL)
+ (void) NPCloseEnum( EnumHandle);
+
+ if (NetR != NULL)
+ {
+ (void) LocalFree( (HLOCAL) NetR);
+ NetR = NULL;
+ }
+
+ return err;
+}
+
+HRESULT
+NWUIAttachAs(
+ HWND hParent,
+ LPNETRESOURCE pNetRes
+)
+{
+ DWORD err = NO_ERROR;
+ WCHAR szServerName[MAX_PATH+1];
+ BOOL fAttached;
+ BOOL fAuthenticated;
+
+ // First, see if we are attached to the server.
+ // Note, Attach as menu will be disabled on the NDS servers that we are already logged into.
+
+ // Need to extract the server name from full UNC path
+ szServerName[0] = szServerName[1] = L'\\';
+ NwExtractServerName( pNetRes->lpRemoteName, szServerName + 2 );
+
+ err = NwIsServerOrTreeAttached( szServerName + 2, &fAttached, &fAuthenticated );
+
+ if ( err == NO_ERROR && fAttached && fAuthenticated )
+ {
+ // Already attached and authenticated to the server.
+ // So, ask the user if he wants to log out first.
+
+ int nRet = ::MsgBoxPrintf( hParent,
+ IDS_MESSAGE_LOGOUT_QUESTION,
+ IDS_TITLE_LOGOUT,
+ MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION );
+
+ if ( nRet != IDYES )
+ return NOERROR;
+
+ BOOL fDisconnected = FALSE; // can be used to refresh the shell if needed
+ err = LogoutFromServer( szServerName + 2, &fDisconnected );
+
+ if ( err != NO_ERROR )
+ {
+ ::MsgBoxPrintf( hParent,
+ IDS_MESSAGE_LOGOUT_FAILED,
+ IDS_TITLE_LOGOUT,
+ MB_OK | MB_SETFOREGROUND | MB_ICONSTOP );
+
+ return NOERROR;
+ }
+ }
+
+ // If error occurred, just assume we are not attached to the server and continue on
+ // to login to the server.
+
+ DWORD dwConnFlags = CONNECT_INTERACTIVE | CONNECT_PROMPT;
+
+ // See if the server is in the default context tree.
+ // If yes, then we don't need to prompt the password first before connecting
+ // in WNetAddConnection3.
+
+ BOOL fInDefaultTree = FALSE;
+ err = NwIsServerInDefaultTree( pNetRes->lpRemoteName, &fInDefaultTree );
+
+ if ( (err == NO_ERROR ) && fInDefaultTree )
+ dwConnFlags = CONNECT_INTERACTIVE;
+
+ //
+ // Now call WNetAddConnection3
+ //
+
+ // NOTE: net use \\mars_srv0 will succeed
+ // but net use \\marsdev\cn=mars_srv0... will failed
+ // Hence, just use the server name to connect.
+ LPWSTR pszSave = pNetRes->lpRemoteName;
+ pNetRes->lpRemoteName = szServerName;
+
+ err = WNetAddConnection3( hParent,
+ pNetRes,
+ NULL,
+ NULL,
+ dwConnFlags );
+
+ if ( err != WN_SUCCESS && err != WN_CANCEL )
+ {
+ ::MsgBoxErrorPrintf( hParent,
+ IDS_MESSAGE_ADDCONN_ERROR,
+ IDS_NETWARE_TITLE,
+ MB_OK | MB_SETFOREGROUND | MB_ICONSTOP,
+ err,
+ pNetRes->lpRemoteName );
+ }
+
+ pNetRes->lpRemoteName = pszSave; // restore the original remote name just in case
+
+ return NOERROR;
+}
+
+
+#if 0
+HRESULT
+NWUISetDefaultContext(
+ HWND hParent,
+ LPNETRESOURCE pNetRes
+)
+{
+ DWORD dwPrintOptions;
+ LPWSTR pszCurrentContext = NULL;
+ WCHAR szNewContext[MAX_PATH+1];
+
+ DWORD err = NO_ERROR;
+ HANDLE handleRdr = NULL;
+
+ UNICODE_STRING uTree;
+ UNICODE_STRING uContext;
+ LPWSTR pszContext = NULL;
+
+ // Open a handle to the redirector
+ err = RtlNtStatusToDosError( ::NwNdsOpenRdrHandle( &handleRdr ));
+
+ if ( err != NO_ERROR )
+ goto CleanExit;
+
+ // Get the print option so that we can use it later
+ err = ::NwQueryInfo( &dwPrintOptions, &pszCurrentContext );
+
+ if ( err != NO_ERROR )
+ goto CleanExit;
+
+ wcscpy( szNewContext, pNetRes->lpRemoteName + 1 ); // get past 1st '\\'
+ szNewContext[0] = TREECHAR; // in the format "*TREE\CONTEXT"
+
+ if ( (pszContext = wcschr( szNewContext, L'\\' )) != NULL )
+ {
+ *pszContext = 0;
+ RtlInitUnicodeString( &uContext, pszContext + 1 );
+ }
+ else
+ RtlInitUnicodeString( &uContext, L"");
+
+ RtlInitUnicodeString( &uTree, szNewContext+1 );
+
+ if ( (err = RtlNtStatusToDosError( ::NwNdsSetTreeContext( handleRdr, &uTree, &uContext)))
+ == NO_ERROR )
+ {
+ *pszContext = L'\\';
+
+ if ((err = ::NwSetInfoInRegistry( dwPrintOptions, szNewContext )) == NO_ERROR )
+ {
+ ::MsgBoxPrintf( hParent,
+ IDS_MESSAGE_CONTEXT_CHANGED,
+ IDS_NETWARE_TITLE,
+ MB_OK | MB_SETFOREGROUND | MB_ICONINFORMATION,
+ pszCurrentContext
+ ? ( *pszCurrentContext == TREECHAR
+ ? pszCurrentContext + 1
+ : pszCurrentContext )
+ : L"",
+ szNewContext+1 );
+ }
+ }
+
+CleanExit:
+
+ if ( err != NO_ERROR )
+ {
+ ::MsgBoxErrorPrintf( hParent,
+ IDS_MESSAGE_CONTEXT_ERROR,
+ IDS_NETWARE_TITLE,
+ MB_OK | MB_SETFOREGROUND | MB_ICONSTOP,
+ err,
+ szNewContext+1);
+ }
+
+ if ( pszCurrentContext != NULL )
+ {
+ LocalFree( pszCurrentContext );
+ pszCurrentContext = NULL;
+ }
+
+ if ( handleRdr != NULL )
+ {
+ ::NtClose( handleRdr );
+ handleRdr = NULL;
+ }
+
+ return NOERROR;
+}
+#endif
+
+HRESULT
+NWUIMapNetworkDrive(
+ HWND hParent,
+ LPNETRESOURCE pNetRes
+)
+{
+ HRESULT hres;
+ CONNECTDLGSTRUCT cds;
+
+ cds.cbStructure = sizeof(cds);
+ cds.hwndOwner = hParent;
+ cds.lpConnRes = pNetRes;
+ cds.dwFlags = CONNDLG_RO_PATH;
+
+ if ( (( hres = WNetConnectionDialog1( &cds )) == WN_SUCCESS )
+ && ( g_pFuncSHChangeNotify )
+ )
+ {
+ WCHAR szPath[4];
+
+ szPath[0] = ((USHORT) cds.dwDevNum) - 1 + L'A';
+ szPath[1] = L':';
+ szPath[2] = L'\\';
+ szPath[3] = 0;
+
+ // Notify shell about added redirection
+ (*g_pFuncSHChangeNotify)( SHCNE_DRIVEADD,
+ SHCNF_FLUSH | SHCNF_PATH,
+ szPath,
+ NULL );
+
+ // And we need to open shell window on this path
+ if (g_pFuncSHExecuteEx)
+ {
+ SHELLEXECUTEINFO ExecInfo;
+
+ ::memset(&ExecInfo,0,sizeof(ExecInfo));
+
+ ExecInfo.hwnd = hParent;
+ ExecInfo.lpVerb = 0;
+ ExecInfo.lpFile = szPath;
+ ExecInfo.lpParameters = NULL;
+ ExecInfo.lpDirectory = NULL;
+ ExecInfo.nShow = SW_NORMAL | SW_SHOW;
+ ExecInfo.fMask = SEE_MASK_CLASSNAME;
+ ExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
+ ExecInfo.lpClass = (LPWSTR) L"Folder";
+ ExecInfo.hkeyClass = NULL;
+
+ (*g_pFuncSHExecuteEx)(&ExecInfo);
+ }
+ }
+
+ return hres;
+}
+
+
+
+#define LB_PCT_NAME 25
+#define LB_PCT_TYPE 11
+#define LB_PCT_CONN 11
+#define LB_PCT_USER 25
+#define LB_PCT_STATUS 27
+
+#define BITMAP_WIDTH 16
+#define BITMAP_HEIGHT 16
+
+#define MAPCOLOR RGB(0, 255, 0)
+
+static UINT uiNDSIconIndex = 0;
+static UINT uiServerIconIndex = 0;
+
+/*
+ * FillConnectionsListView
+ * -----------------------
+ *
+ * Fill list box with information on active connections
+ */
+VOID
+FillConnectionsListView(
+ HWND hwndDlg
+)
+{
+ HWND hwndLV = ::GetDlgItem(hwndDlg,IDD_GLOBAL_SERVERLIST);
+ LV_ITEM lvI;
+ WCHAR szSubItemText[MAX_PATH+1];
+ UINT uiInsertedIndex;
+
+ DWORD ResumeKey = 0;
+ LPBYTE pConnBuffer = NULL;
+ DWORD EntriesRead = 0;
+ DWORD err = NO_ERROR;
+
+ // Prepare ListView structure
+ lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
+ lvI.state = 0;
+ lvI.stateMask = 0;
+
+ do {
+
+ if ( pConnBuffer != NULL )
+ {
+ LocalFree( pConnBuffer );
+ pConnBuffer = NULL;
+ }
+
+ err = NwGetConnectionStatus( NULL,
+ &ResumeKey,
+ &pConnBuffer,
+ &EntriesRead );
+
+
+ if ( ( err != NO_ERROR )
+ || ( EntriesRead == 0 )
+ )
+ {
+ goto CleanExit;
+ }
+
+ PCONN_STATUS pConnStatus = (PCONN_STATUS) pConnBuffer;
+
+ for ( DWORD i = 0; i < EntriesRead; i++)
+ {
+ // Allocate and initialize new item structure for use in the listbox
+
+ DWORD dwSize;
+
+ //
+ // Don't need to show preferred server with only implicit
+ // connections since we can't disconnect from it.
+ //
+ if ( pConnStatus->fPreferred )
+ {
+ // Continue with the next item
+ pConnStatus = (PCONN_STATUS) ( (DWORD) pConnStatus
+ + pConnStatus->dwTotalLength);
+ continue;
+ }
+
+ //
+ // Allocate and copy the connection information to be store with
+ // the listbox
+ //
+ PCONN_STATUS pConnStatusKeep =
+ (PCONN_STATUS) LocalAlloc( LMEM_ZEROINIT, pConnStatus->dwTotalLength );
+ if ( pConnStatusKeep == NULL )
+ {
+ err = ERROR_NOT_ENOUGH_MEMORY;
+ goto CleanExit;
+ }
+
+ memcpy( pConnStatusKeep, pConnStatus, pConnStatus->dwTotalLength );
+
+ dwSize = sizeof(CONN_STATUS);
+
+ if ( pConnStatus->pszServerName )
+ {
+ pConnStatusKeep->pszServerName =
+ (LPWSTR) ((DWORD)pConnStatusKeep + dwSize );
+
+ NwMakePrettyDisplayName( pConnStatusKeep->pszServerName );
+
+ dwSize += (wcslen(pConnStatus->pszServerName)+1)*sizeof(WCHAR);
+ }
+
+ if ( pConnStatus->pszUserName )
+ {
+ pConnStatusKeep->pszUserName =
+ (LPWSTR) ((DWORD)pConnStatusKeep + dwSize );
+
+ dwSize += (wcslen(pConnStatus->pszUserName)+1) * sizeof(WCHAR);
+
+ NwAbbreviateUserName( pConnStatus->pszUserName,
+ pConnStatusKeep->pszUserName );
+
+ NwMakePrettyDisplayName( pConnStatusKeep->pszUserName );
+ }
+
+ if ( pConnStatus->pszTreeName )
+ {
+ pConnStatusKeep->pszTreeName =
+ (LPWSTR) ((DWORD)pConnStatusKeep + dwSize );
+ }
+
+ //
+ // Construct the item to add to the listbox
+ //
+ lvI.iItem = i;
+ lvI.iSubItem = 0;
+ lvI.pszText = szSubItemText;
+ lvI.cchTextMax = sizeof(szSubItemText);
+
+ // Select proper icon
+ lvI.iImage = pConnStatusKeep->fNds? uiNDSIconIndex
+ : uiServerIconIndex;
+
+ lvI.lParam = (LPARAM) pConnStatusKeep;
+
+ wcscpy( szSubItemText, pConnStatusKeep->pszServerName );
+
+ // Insert the item
+ uiInsertedIndex = ListView_InsertItem( hwndLV, &lvI);
+
+ if ( uiInsertedIndex != -1 )
+ {
+ // Added item itself - now for specific columns
+
+ // First, add the column indicating bindery or nds connection
+ if ( pConnStatusKeep->fNds )
+ {
+ LoadString( ::hmodNW, IDS_LOGIN_TYPE_NDS, szSubItemText,
+ sizeof(szSubItemText)/sizeof(szSubItemText[0]));
+ }
+ else
+ {
+ LoadString( ::hmodNW, IDS_LOGIN_TYPE_BINDERY, szSubItemText,
+ sizeof(szSubItemText)/sizeof(szSubItemText[0]));
+ }
+
+ ListView_SetItemText( hwndLV,
+ uiInsertedIndex,
+ 1, // SubItem id
+ szSubItemText );
+
+ // Next, Add the column indicating the connection number
+
+ if ( ( pConnStatusKeep->pszServerName[0] != TREECHAR )
+ && ( pConnStatusKeep->dwConnType != NW_CONN_DISCONNECTED )
+ )
+ {
+ // Add connection number only if it is a connection
+ // to a server and not a tree.
+ // A connection number only makes sense when not disconnected
+ ::wsprintf(szSubItemText,L"%4d",pConnStatusKeep->nConnNum );
+ ListView_SetItemText( hwndLV,
+ uiInsertedIndex,
+ 2, // SubItem id
+ szSubItemText );
+ }
+
+ // Then, add the column indicating the user name
+
+ *szSubItemText = L'\0';
+ if ( pConnStatusKeep->pszUserName )
+ {
+ wcscpy( szSubItemText, pConnStatusKeep->pszUserName );
+
+ ListView_SetItemText( hwndLV,
+ uiInsertedIndex,
+ 3, // SubItem id
+ szSubItemText );
+ }
+
+ // Last of all, add the column indicating the connection status
+
+ *szSubItemText = L'\0';
+ GetConnectionStatusString( pConnStatusKeep,
+ (LPBYTE) szSubItemText,
+ sizeof(szSubItemText)/sizeof(szSubItemText[0]));
+
+ ListView_SetItemText( hwndLV,
+ uiInsertedIndex,
+ 4, // SubItem id
+ szSubItemText );
+
+ }
+ else
+ {
+ // Failed inserting item in the list,
+ // need to delete the allocated CONN_STATUS
+ ASSERT( FALSE );
+ LocalFree( pConnStatusKeep );
+ pConnStatusKeep = NULL;
+ }
+
+ // Continue with the next item
+ pConnStatus = (PCONN_STATUS) ( (DWORD) pConnStatus
+ + pConnStatus->dwTotalLength);
+ }
+
+ } while ( ResumeKey != 0 );
+
+CleanExit:
+
+ if ( pConnBuffer != NULL )
+ {
+ LocalFree( pConnBuffer );
+ pConnBuffer = NULL;
+ }
+
+ if ( err != NO_ERROR )
+ {
+ // If error occurred, we will end the dialog
+
+ ::MsgBoxErrorPrintf( hwndDlg,
+ IDS_MESSAGE_CONNINFO_ERROR,
+ IDS_NETWARE_TITLE,
+ MB_OK | MB_SETFOREGROUND | MB_ICONSTOP,
+ err,
+ NULL );
+
+ ::EndDialog( hwndDlg, FALSE);
+ }
+}
+
+
+/*
+ * CreateConnectionsListView
+ * -------------------------
+ *
+ * Initialize the column headers of the list box
+ */
+VOID
+CreateConnectionsListView(
+ HWND hwndDlg
+)
+{
+ HWND hwndLV;
+ HIMAGELIST hSmall;
+ UINT uiLBoxWidth;
+
+ InitCommonControls();
+
+ // Get the handle of the listbox
+ hwndLV = ::GetDlgItem(hwndDlg,IDD_GLOBAL_SERVERLIST);
+
+ RECT rc;
+ ::GetWindowRect( ::GetDlgItem( hwndDlg, IDD_GLOBAL_SERVERLIST ), &rc );
+ uiLBoxWidth = rc.right - rc.left;
+
+ // Load image list
+ hSmall = ::ImageList_Create(BITMAP_WIDTH,BITMAP_HEIGHT,ILC_MASK,4,0);
+
+ // Load bitmap of the tree/server icon
+ HBITMAP hbm;
+ hbm = ::LoadBitmap(::hmodNW,MAKEINTRESOURCE(IDB_TREE_ICON));
+ if ((uiNDSIconIndex = ImageList_AddMasked(hSmall,hbm,MAPCOLOR)) == -1)
+ ASSERT(FALSE);
+
+ hbm = ::LoadBitmap(::hmodNW,MAKEINTRESOURCE(IDB_SERVER_ICON));
+ if ((uiServerIconIndex = ImageList_AddMasked(hSmall,hbm,MAPCOLOR)) == -1)
+ ASSERT(FALSE);
+
+ ImageList_SetBkColor(hSmall, CLR_NONE);
+
+ // Associate image list with list view control
+ ListView_SetImageList(hwndLV,hSmall,LVSIL_SMALL);
+
+ // Initialize columns in header
+ LV_COLUMN lvC;
+ UINT uiColumnIndex = 0;
+ WCHAR szColumnName[128];
+
+ lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
+ lvC.fmt = LVCFMT_LEFT;
+ lvC.cx = (uiLBoxWidth*LB_PCT_NAME)/100;
+ lvC.pszText = szColumnName;
+
+ // Add the column header representing the server name
+ *szColumnName = L'\0';
+ ::LoadString( ::hmodNW,
+ IDS_COLUMN_NAME,
+ szColumnName,
+ sizeof(szColumnName)/sizeof(szColumnName[0]));
+ if ( ListView_InsertColumn(hwndLV,uiColumnIndex++,&lvC) == -1)
+ ASSERT(FALSE);
+
+
+ // Add the column header representing the conneciton type
+ *szColumnName = L'\0';
+ lvC.cx = (uiLBoxWidth*LB_PCT_TYPE)/100;
+ ::LoadString( ::hmodNW,
+ IDS_COLUMN_CONN_TYPE,
+ szColumnName,
+ sizeof(szColumnName)/sizeof(szColumnName[0]));
+ if ( ListView_InsertColumn(hwndLV,uiColumnIndex++,&lvC) == -1)
+ ASSERT(FALSE);
+
+ // Add the column header representing the connection number
+ *szColumnName = L'\0';
+ lvC.cx = (uiLBoxWidth*LB_PCT_CONN)/100;
+ lvC.fmt = LVCFMT_RIGHT;
+
+ ::LoadString( ::hmodNW,
+ IDS_COLUMN_CONN_NUMBER,
+ szColumnName,
+ sizeof(szColumnName)/sizeof(szColumnName[0]));
+ if ( ListView_InsertColumn(hwndLV,uiColumnIndex++,&lvC) == -1)
+ ASSERT(FALSE);
+
+ // Add the column header representing the name of the user
+ *szColumnName = L'\0';
+ lvC.cx = (uiLBoxWidth*LB_PCT_USER)/100;
+ lvC.fmt = LVCFMT_LEFT;
+
+ ::LoadString( ::hmodNW,
+ IDS_COLUMN_USER,
+ szColumnName,
+ sizeof(szColumnName)/sizeof(szColumnName[0]));
+
+ if ( ListView_InsertColumn(hwndLV,uiColumnIndex++,&lvC) == -1)
+ ASSERT(FALSE);
+
+ // Add the column header representing the status of the connection
+ *szColumnName = L'\0';
+ lvC.cx = (uiLBoxWidth*LB_PCT_STATUS)/100;
+ lvC.fmt = LVCFMT_LEFT;
+
+ ::LoadString( ::hmodNW,
+ IDS_COLUMN_STATUS,
+ szColumnName,
+ sizeof(szColumnName)/sizeof(szColumnName[0]));
+
+ if ( ListView_InsertColumn(hwndLV,uiColumnIndex++,&lvC) == -1)
+ ASSERT(FALSE);
+
+ // Now fill list view window with connection information
+ FillConnectionsListView( hwndDlg );
+
+} /* endproc CreateConnectionsListView */
+
+
+/*
+ * GlobalWhoAmI_ListViewCompareProc
+ * --------------------------------
+ *
+ */
+LRESULT CALLBACK
+GlobalWhoAmI_ListViewCompareProc(
+ LPARAM lParam1,
+ LPARAM lParam2,
+ LPARAM lParamSort
+)
+{
+ PCONN_STATUS pConnItem1 = (PCONN_STATUS)lParam1;
+ PCONN_STATUS pConnItem2 = (PCONN_STATUS)lParam2;
+
+ int iResult = 0;
+
+ if ( pConnItem1 && pConnItem2 )
+ {
+ switch(lParamSort)
+ {
+ case 0:
+ iResult = ::_wcsicmp( pConnItem1->pszServerName,
+ pConnItem2->pszServerName);
+ break;
+
+ case 1:
+ iResult = pConnItem1->fNds - pConnItem2->fNds;
+ break;
+
+ case 2:
+ iResult = pConnItem1->nConnNum - pConnItem2->nConnNum;
+ break;
+
+ case 3:
+ {
+ // pszUserName might be NULL, so we need to be careful when
+ // comparing them.
+ if ( pConnItem1->pszUserName )
+ {
+ if ( pConnItem2->pszUserName )
+ {
+ iResult = ::_wcsicmp( pConnItem1->pszUserName,
+ pConnItem2->pszUserName);
+ }
+ else
+ {
+ iResult = 1;
+ }
+ }
+ else
+ {
+ iResult = -1;
+ }
+ break;
+ }
+
+ case 4:
+ iResult = pConnItem1->dwConnType - pConnItem2->dwConnType;
+ break;
+
+ default:
+ iResult = 0;
+ break;
+ }
+ }
+
+ return (iResult);
+
+}
+
+LRESULT
+NotifyHandler(
+ HWND hwndDlg,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam
+)
+{
+ NM_LISTVIEW *lpNm = (NM_LISTVIEW *)lParam;
+ NMHDR *lphdr = &lpNm->hdr;
+
+ HWND hwndLV = ::GetDlgItem(hwndDlg,IDD_GLOBAL_SERVERLIST);
+
+ switch(lphdr->code)
+ {
+ case LVN_ITEMCHANGED:
+ // Check for change in item state, make sure item has received focus
+ if (lpNm->uChanged & LVIF_STATE)
+ {
+ UINT uiSelectedItems = 0;
+
+ uiSelectedItems = ListView_GetSelectedCount(hwndLV);
+
+ EnableWindow( GetDlgItem(hwndDlg, IDD_DETACH),
+ uiSelectedItems? TRUE : FALSE);
+
+ return TRUE;
+ }
+ break;
+
+ case LVN_COLUMNCLICK:
+ ListView_SortItems( hwndLV,
+ GlobalWhoAmI_ListViewCompareProc,
+ (LPARAM)(lpNm->iSubItem));
+ return TRUE; /* we processed a message */
+
+ case LVN_DELETEITEM:
+ // Free memory
+ LocalFree( (HLOCAL) lpNm->lParam );
+ lpNm->lParam = NULL;
+ break;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+
+BOOL
+DetachResourceProc(
+ HWND hwndDlg
+)
+{
+ BOOL fDetached = FALSE;
+ LV_ITEM lvitem;
+ int index;
+ DWORD err;
+
+ HWND hwndLV = ::GetDlgItem( hwndDlg, IDD_GLOBAL_SERVERLIST);
+
+ index = -1; // Start at beginning of item list.
+
+ while ((index = ListView_GetNextItem(hwndLV, index, LVNI_SELECTED)) != -1)
+ {
+ lvitem.iItem = index;
+ lvitem.mask = LVIF_PARAM;
+ lvitem.iSubItem = 0;
+
+ if ( ListView_GetItem( hwndLV, &lvitem ))
+ {
+ PCONN_STATUS pConnStatus = (PCONN_STATUS) lvitem.lParam;
+ BOOL fDisconnected = FALSE; // Can be used to refresh
+ // the shell if needed
+
+ err = LogoutFromServer( pConnStatus->pszServerName,
+ &fDisconnected );
+
+ if ( err == NO_ERROR )
+ {
+ fDetached = TRUE;
+ }
+ else
+ {
+ NwMakePrettyDisplayName(pConnStatus->pszServerName);
+ ::MsgBoxPrintf( hwndDlg,
+ IDS_MESSAGE_LOGOUT_FROM_SERVER_FAILED,
+ IDS_TITLE_LOGOUT,
+ MB_OK | MB_SETFOREGROUND | MB_ICONINFORMATION,
+ pConnStatus->pszServerName );
+ }
+ }
+ }
+
+ return fDetached;
+}
+
+static DWORD aWhoAmIIds[] = { IDC_LOGOFRAME, NO_HELP,
+ IDD_GLOBAL_SERVERLIST_T,IDH_GLOBAL_SERVERLIST,
+ IDD_GLOBAL_SERVERLIST, IDH_GLOBAL_SERVERLIST,
+ IDD_DETACH, IDH_GLOBAL_DETACH,
+ IDD_GLOBAL_SVRLIST_DESC,IDH_GLOBAL_SERVERLIST,
+ 0, 0 };
+
+/*
+ * GlobalWhoAmIDlgProc
+ * -------------------
+ *
+ * WhoAmI information for list of attached servers
+ */
+BOOL
+CALLBACK
+GlobalWhoAmIDlgProc(
+ HWND hwndDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ LPWSTR pszCurrentContext = NULL;
+ DWORD dwPrintOptions;
+
+ // Get the current default tree or server name
+ DWORD err = ::NwQueryInfo( &dwPrintOptions, &pszCurrentContext );
+ if ( err == NO_ERROR )
+ {
+ LPWSTR pszName;
+ WCHAR szUserName[MAX_PATH+1] = L"";
+ WCHAR szNoName[2] = L"";
+ DWORD ResumeKey = 0;
+ LPBYTE pBuffer = NULL;
+ DWORD EntriesRead = 0;
+
+ DWORD dwMessageId;
+
+ UNICODE_STRING uContext;
+ WCHAR szContext[MAX_PATH+1];
+
+ szContext[0] = 0;
+ uContext.Buffer = szContext;
+ uContext.Length = uContext.MaximumLength
+ = sizeof(szContext)/sizeof(szContext[0]);
+
+ if ( pszCurrentContext )
+ {
+ pszName = pszCurrentContext;
+ }
+ else
+ {
+ pszName = szNoName;
+ }
+
+ if ( pszName[0] == TREECHAR )
+ {
+ // Get the tree name from the full name *TREE\CONTEXT
+
+ LPWSTR pszTemp;
+ if ( pszTemp = wcschr( pszName, L'\\' ))
+ *pszTemp = 0;
+
+ dwMessageId = IDS_MESSAGE_NOT_LOGGED_IN_TREE;
+ }
+ else
+ {
+ dwMessageId = IDS_MESSAGE_NOT_LOGGED_IN_SERVER;
+ }
+
+ if ( pszName[0] != 0 ) // there is preferred server/tree
+ {
+ err = NwGetConnectionStatus( pszName,
+ &ResumeKey,
+ &pBuffer,
+ &EntriesRead );
+ }
+
+ if ( err == NO_ERROR && EntriesRead > 0 )
+ // For trees, we'll get more than one entry
+ {
+ PCONN_STATUS pConnStatus = (PCONN_STATUS) pBuffer;
+
+ if ( EntriesRead > 1 && pszName[0] == TREECHAR )
+ {
+ // If there is more than one entry for trees,
+ // then we need to find one entry where username is not null.
+ // If we cannot find one, then just use the first one.
+
+ DWORD i;
+ PCONN_STATUS pConnStatusTmp = pConnStatus;
+ PCONN_STATUS pConnStatusUser = NULL;
+ PCONN_STATUS pConnStatusNoUser = NULL;
+
+ for ( i = 0; i < EntriesRead ; i++ )
+ {
+ if ( pConnStatusTmp->fNds )
+ {
+ pConnStatusNoUser = pConnStatusTmp;
+
+ if ( ( pConnStatusTmp->pszUserName != NULL )
+ && ( ( pConnStatusTmp->dwConnType
+ == NW_CONN_NDS_AUTHENTICATED_NO_LICENSE )
+ || ( pConnStatusTmp->dwConnType
+ == NW_CONN_NDS_AUTHENTICATED_LICENSED )
+ )
+ )
+ {
+ // Found it
+ pConnStatusUser = pConnStatusTmp;
+ break;
+ }
+ }
+
+ // Continue with the next item
+ pConnStatusTmp = (PCONN_STATUS)
+ ( (DWORD) pConnStatusTmp
+ + pConnStatusTmp->dwTotalLength);
+ }
+
+ if ( pConnStatusUser )
+ {
+ // found one nds entry with a user name
+ pConnStatus = pConnStatusUser;
+ }
+ else if ( pConnStatusNoUser )
+ {
+ // use an nds entry with no user name
+ pConnStatus = pConnStatusNoUser;
+ }
+ // else use the first entry
+ }
+
+ if ( ( pConnStatus->pszUserName )
+ && ( pConnStatus->pszUserName[0] != 0 )
+ )
+ {
+ NwAbbreviateUserName( pConnStatus->pszUserName,
+ szUserName);
+
+ NwMakePrettyDisplayName( szUserName );
+
+ if ( pszName[0] != TREECHAR )
+ {
+ dwMessageId = IDS_MESSAGE_LOGGED_IN_SERVER;
+ }
+ else
+ {
+ dwMessageId = IDS_MESSAGE_LOGGED_IN_TREE;
+ }
+ }
+
+ if ( pszName[0] == TREECHAR )
+ {
+ // For trees, we need to get the current context
+
+ // Open a handle to the redirector
+ HANDLE handleRdr = NULL;
+ err = RtlNtStatusToDosError(
+ ::NwNdsOpenRdrHandle( &handleRdr ));
+
+ if ( err == NO_ERROR )
+ {
+ UNICODE_STRING uTree;
+ RtlInitUnicodeString( &uTree, pszName+1 ); // get past '*'
+
+ // Get the current context in the default tree
+ err = RtlNtStatusToDosError(
+ ::NwNdsGetTreeContext( handleRdr,
+ &uTree,
+ &uContext));
+ }
+
+ if ( handleRdr != NULL )
+ ::NtClose( handleRdr );
+ }
+ }
+
+ if ( !err )
+ {
+ LPWSTR pszText = NULL;
+ err = ::LoadMsgPrintf( &pszText,
+ dwMessageId,
+ pszName[0] == TREECHAR?
+ pszName + 1 : pszName,
+ szUserName,
+ szContext );
+
+ if ( err == NO_ERROR )
+ {
+ ::SetDlgItemText( hwndDlg, IDD_GLOBAL_SERVERLIST_T,
+ pszText);
+ ::LocalFree( pszText );
+ }
+ }
+
+ if ( pBuffer != NULL )
+ {
+ LocalFree( pBuffer );
+ pBuffer = NULL;
+ }
+ }
+
+ if ( pszCurrentContext != NULL )
+ {
+ LocalFree( pszCurrentContext );
+ pszCurrentContext = NULL;
+ }
+
+ if ( err != NO_ERROR )
+ {
+ ::MsgBoxErrorPrintf( hwndDlg,
+ IDS_MESSAGE_CONNINFO_ERROR,
+ IDS_NETWARE_TITLE,
+ MB_OK | MB_SETFOREGROUND | MB_ICONSTOP,
+ err,
+ NULL );
+ ::EndDialog( hwndDlg, FALSE);
+ return TRUE;
+ }
+
+ // Fill listview control with connection parameters
+ CreateConnectionsListView(hwndDlg);
+
+ UnHideControl( hwndDlg, IDD_DETACH);
+
+ // List view fill defaults to no selected server, disable Detach.
+ EnableWindow( GetDlgItem( hwndDlg, IDD_DETACH), FALSE);
+
+ // Set up timer for automatic refresh interval
+ ::SetTimer( hwndDlg, 1, GLOBAL_WHOAMI_REFRESH_INTERVAL, NULL);
+
+ // Set focus to list box
+ ::SetFocus( ::GetDlgItem( hwndDlg, IDD_GLOBAL_SERVERLIST));
+
+ return FALSE; /* we set the focus */
+ }
+
+ case WM_DESTROY:
+ ::KillTimer( hwndDlg, 1);
+ break;
+
+ case WM_COMMAND:
+
+ switch (wParam)
+ {
+ case IDOK:
+ case IDCANCEL:
+ ::EndDialog( hwndDlg, FALSE);
+ return TRUE; /* we processed a message */
+
+ case IDD_DETACH:
+ // Attempt to detach server connection currently selected
+ if ( DetachResourceProc( hwndDlg ))
+ {
+ // If succeeded - refresh window
+ ::SendMessage(hwndDlg,WM_COMMAND,IDD_REFRESH,0L);
+ }
+
+ return TRUE; /* we processed a message */
+
+ case IDD_REFRESH:
+ {
+ // Refresh connection listbox
+
+ HWND hwndLV = ::GetDlgItem( hwndDlg, IDD_GLOBAL_SERVERLIST);
+
+ ::SetFocus( hwndLV );
+
+ // Clear list
+ ListView_DeleteAllItems( hwndLV );
+
+ // Now refill list view window
+ FillConnectionsListView( hwndDlg );
+
+ // List view refill unsets selected server focus, disable Detach.
+ EnableWindow( GetDlgItem( hwndDlg, IDD_DETACH ), FALSE );
+
+ return TRUE; /* we processed a message */
+ }
+
+ default:
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ // Handle notifications
+ if ( NotifyHandler( hwndDlg, msg, wParam, lParam))
+ return TRUE; /* we processed a message */
+ break;
+
+ case WM_TIMER:
+ ::SendMessage( hwndDlg, WM_COMMAND, IDD_REFRESH, 0L);
+ break;
+
+ case WM_HELP:
+ ::WinHelp( (HWND) ((LPHELPINFO)lParam)->hItemHandle,
+ NW_HELP_FILE,
+ HELP_WM_HELP,
+ (DWORD) (LPVOID) aWhoAmIIds );
+ return TRUE;
+
+ case WM_CONTEXTMENU:
+ ::WinHelp( (HWND) wParam,
+ NW_HELP_FILE,
+ HELP_CONTEXTMENU,
+ (DWORD) (LPVOID) aWhoAmIIds );
+ return TRUE;
+
+ }
+
+ return FALSE; /* we didn't process the message */
+
+}