summaryrefslogtreecommitdiffstats
path: root/private/nw/svcdlls/nwwks/client/nwshmenu.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'private/nw/svcdlls/nwwks/client/nwshmenu.cxx')
-rw-r--r--private/nw/svcdlls/nwwks/client/nwshmenu.cxx896
1 files changed, 896 insertions, 0 deletions
diff --git a/private/nw/svcdlls/nwwks/client/nwshmenu.cxx b/private/nw/svcdlls/nwwks/client/nwshmenu.cxx
new file mode 100644
index 000000000..d4cc28bdb
--- /dev/null
+++ b/private/nw/svcdlls/nwwks/client/nwshmenu.cxx
@@ -0,0 +1,896 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ nwshmenu.cxx
+
+Abstract:
+
+ This module implements the IContextMenu member functions necessary to support
+ the context menu of NetWare shell extension.
+
+Author:
+
+ Yi-Hsin Sung (yihsins) 25-Oct-1995
+
+--*/
+
+
+extern "C"
+{
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <shellapi.h>
+#include <shlobj.h>
+#define DONT_WANT_SHELLDEBUG
+#include <shsemip.h>
+#include <winnetwk.h>
+#include <ntddnwfs.h>
+#include "nwshrc.h"
+#include "nwwks.h"
+#include "nwutil.h"
+}
+
+#include "nwshcmn.h"
+#include "nwshext.h"
+
+#define MAX_VERB_SIZE 128
+#define MAX_SHELL_IDLIST_SIZE 512
+
+BOOL g_cfNetResource = 0; // Clipboard format
+BOOL g_cfIDList = 0;
+
+NWMENUITEM aServerVerbs[] = { { IDO_VERB_WHOAMI, 0 },
+ { IDO_VERB_LOGOUT, 0 },
+ { IDO_VERB_ATTACHAS, 0 },
+ { 0, 0 } };
+
+NWMENUITEM aDSVerbs[] = { { IDO_VERB_TREEWHOAMI, 0 },
+ // { IDO_VERB_SETDEFAULTCONTEXT, 0 },
+ { 0, 0 } };
+
+NWMENUITEM aDSTreeVerbs[] = { { IDO_VERB_TREEWHOAMI, 0 },
+ { 0, 0 } };
+
+NWMENUITEM aGlobalVerbs[] = { { IDO_VERB_GLOBALWHOAMI, 0 },
+ { 0, 0 } };
+
+NWMENUITEM aDirectoryVerbs[] = { { IDO_VERB_MAPNETWORKDRIVE, 0 },
+ { 0, 0 } };
+
+
+NWMENUITEM aHoodVerbs[] = { { IDO_VERB_GLOBALWHOAMI, 0 },
+ { 0, 0 } };
+
+
+HRESULT
+InsertCommandsArray( HMENU hMenu,
+ UINT indexMenu,
+ UINT idCmdFirst,
+ LPNWMENUITEM aVerbs );
+
+UINT
+LookupCommand( LPNWMENUITEM aVerbs,
+ LPCSTR pszCmd );
+
+UINT
+LookupResource( LPNWMENUITEM aVerbs,
+ UINT uiResourceOffset );
+
+UINT WINAPI
+HIDA_GetIDList( LPIDA hida,
+ UINT i,
+ LPITEMIDLIST pidlOut,
+ UINT cbMax);
+
+//
+// FUNCTION: CNWObjContextMenu::QueryContextMenu(HMENU, UINT, UINT, UINT, UINT)
+//
+// PURPOSE: Called by the shell just before the context menu is displayed.
+// This is where you add your specific menu items.
+//
+// PARAMETERS:
+// hMenu - Handle to the context menu
+// indexMenu - Index of where to begin inserting menu items
+// idCmdFirst - Lowest value for new menu ID's
+// idCmtLast - Highest value for new menu ID's
+// uFlags - Specifies the context of the menu event
+//
+// RETURN VALUE:
+//
+//
+// COMMENTS:
+//
+
+STDMETHODIMP CNWObjContextMenu::QueryContextMenu( HMENU hMenu,
+ UINT indexMenu,
+ UINT idCmdFirst,
+ UINT idCmdLast,
+ UINT uFlags )
+{
+ HRESULT hres;
+ LPNETRESOURCE pNetRes = (LPNETRESOURCE) _buffer;
+
+ if ( !::GetNetResourceFromShell( _pDataObj,
+ pNetRes,
+ sizeof( _buffer )))
+ {
+ // We cannot get the net resource of the selected object.
+
+ // Must return number of menu items we added.
+ // Nothing added here.
+ return ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 0 ));
+ }
+
+ // First, add a menu separator
+ if ( InsertMenu( hMenu, indexMenu, MF_SEPARATOR | MF_BYPOSITION, 0, NULL))
+ indexMenu++;
+
+ // Next, add menu items depending on display types
+ switch ( pNetRes->dwDisplayType )
+ {
+ case RESOURCEDISPLAYTYPE_ROOT:
+ case RESOURCEDISPLAYTYPE_NETWORK:
+ hres = InsertCommandsArray( hMenu, indexMenu,
+ idCmdFirst, _pIdTable = aGlobalVerbs );
+
+ break;
+
+ case RESOURCEDISPLAYTYPE_TREE:
+ hres = InsertCommandsArray( hMenu, indexMenu,
+ idCmdFirst, _pIdTable = aDSTreeVerbs );
+ break;
+
+ case RESOURCEDISPLAYTYPE_NDSCONTAINER:
+ hres = InsertCommandsArray( hMenu, indexMenu,
+ idCmdFirst, _pIdTable = aDSVerbs );
+ break;
+
+ case RESOURCEDISPLAYTYPE_SERVER:
+ {
+ // BUGBUG: Do we need to check if the server name is local
+ // and disallow operation???
+
+ hres = InsertCommandsArray( hMenu, indexMenu,
+ idCmdFirst, _pIdTable = aServerVerbs );
+
+ if (!SUCCEEDED(hres))
+ break;
+
+ LPBYTE pBuffer = NULL;
+ DWORD EntriesRead = 0;
+ DWORD ResumeKey = 0;
+ WCHAR szServerName[MAX_PATH + 1];
+
+ NwExtractServerName( pNetRes->lpRemoteName, szServerName );
+
+ // See if we are connected.
+ DWORD err = NwGetConnectionStatus( szServerName,
+ &ResumeKey,
+ &pBuffer,
+ &EntriesRead );
+
+ if ( err == NO_ERROR && EntriesRead > 0 )
+ {
+ PCONN_STATUS pConnStatus = (PCONN_STATUS) pBuffer;
+
+ ASSERT( EntriesRead == 1 );
+
+ if ( pConnStatus->fPreferred )
+ {
+ // This is a implicit preferred server connection
+ // so, don't show the connection and don't let the user
+ // logout of it since rdr doesn't allow it.
+ ::EnableMenuItem( hMenu,
+ LookupResource( aServerVerbs,
+ IDO_VERB_LOGOUT),
+ MF_GRAYED | MF_BYCOMMAND);
+
+ }
+ else if ( pConnStatus->fNds )
+ {
+ BOOL fInDefaultTree = FALSE;
+
+ err = NwIsServerInDefaultTree( pNetRes->lpRemoteName, &fInDefaultTree );
+
+ if ( (err == NO_ERROR) && fInDefaultTree )
+ {
+ // NDS connection and in the default tree, disable the Attach As button
+ ::EnableMenuItem( hMenu,
+ LookupResource( aServerVerbs,
+ IDO_VERB_ATTACHAS),
+ MF_GRAYED | MF_BYCOMMAND );
+ }
+ }
+ }
+ else
+ {
+ // If we are not attached or if error occurred when getting
+ // connection status, then disable the Logout button.
+ ::EnableMenuItem( hMenu,
+ LookupResource( aServerVerbs,
+ IDO_VERB_LOGOUT),
+ MF_GRAYED | MF_BYCOMMAND);
+ }
+
+ if ( pBuffer != NULL )
+ {
+ LocalFree( pBuffer );
+ pBuffer = NULL;
+ }
+ break;
+ }
+
+ default:
+ // Must return number of menu items we added.
+ // Nothing added here.
+ hres = ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 0 ));
+ break;
+
+ }
+
+ return hres;
+}
+
+//
+// FUNCTION: CNWObjContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO)
+//
+// PURPOSE: Called by the shell after the user has selected on of the
+// menu items that was added in QueryContextMenu().
+//
+// PARAMETERS:
+// lpcmi - Pointer to an CMINVOKECOMMANDINFO structure
+//
+// RETURN VALUE:
+//
+//
+// COMMENTS:
+//
+
+STDMETHODIMP CNWObjContextMenu::InvokeCommand( LPCMINVOKECOMMANDINFO lpcmi )
+{
+ HRESULT hres = ResultFromScode(E_INVALIDARG);
+ UINT idCmd = LookupCommand( _pIdTable , lpcmi->lpVerb );
+
+ if ( !idCmd )
+ return hres;
+
+ LPNETRESOURCE pNetRes = (LPNETRESOURCE) _buffer;
+
+ switch ( idCmd )
+ {
+ case IDO_VERB_GLOBALWHOAMI:
+ hres = NWUIGlobalWhoAmI( lpcmi->hwnd );
+ break;
+
+ case IDO_VERB_TREEWHOAMI:
+ hres = NWUIWhoAmI( lpcmi->hwnd, pNetRes );
+ break;
+
+#if 0
+ case IDO_VERB_SETDEFAULTCONTEXT:
+ hres = NWUISetDefaultContext( lpcmi->hwnd, pNetRes );
+ break;
+#endif
+
+ case IDO_VERB_WHOAMI:
+ hres = NWUIWhoAmI( lpcmi->hwnd, pNetRes );
+ break;
+
+ case IDO_VERB_LOGOUT:
+ {
+ BOOL fDisconnected = FALSE;
+ hres = NWUILogOut( lpcmi->hwnd, pNetRes, &fDisconnected );
+ if ( hres == NOERROR && fDisconnected )
+ {
+ // Logout is successful, need to notify shell
+
+ FORMATETC fmte = { g_cfIDList ? g_cfIDList
+ : (g_cfIDList=RegisterClipboardFormat( CFSTR_SHELLIDLIST)),
+ (DVTARGETDEVICE FAR *)NULL,
+ DVASPECT_CONTENT,
+ -1,
+ TYMED_HGLOBAL };
+ STGMEDIUM medium;
+
+ hres = _pDataObj->GetData( &fmte, &medium);
+
+ if (SUCCEEDED(hres))
+ {
+ // We got pointer to IDList
+ LPIDA pida = (LPIDA)GlobalLock(medium.hGlobal);
+
+ if ( pida )
+ {
+ BYTE BufIDList[MAX_SHELL_IDLIST_SIZE];
+ LPITEMIDLIST pidl = (LPITEMIDLIST) BufIDList;
+
+ if ( pidl )
+ {
+ // Convert IDA to IDList for this call
+ HIDA_GetIDList( pida,
+ 0, // One object should present
+ pidl ,
+ MAX_SHELL_IDLIST_SIZE);
+
+ // Call SHchangeNotify
+ g_pFuncSHChangeNotify( SHCNE_SERVERDISCONNECT,
+ SHCNF_IDLIST,
+ pidl,
+ NULL);
+ }
+
+ GlobalUnlock(medium.hGlobal);
+ }
+ }
+
+ }
+ break;
+ }
+
+ case IDO_VERB_ATTACHAS:
+ hres = NWUIAttachAs( lpcmi->hwnd, pNetRes );
+ break;
+ }
+
+ return hres;
+}
+
+
+//
+// FUNCTION: CNWObjContextMenu::GetCommandString( UINT, UINT, UINT FAR *, LPSTR, UINT )
+//
+// PURPOSE: Called by the shell after the user has selected on of the
+// menu items that was added in QueryContextMenu().
+//
+// PARAMETERS:
+//
+// RETURN VALUE:
+//
+//
+// COMMENTS:
+//
+
+STDMETHODIMP CNWObjContextMenu::GetCommandString( UINT idCmd,
+ UINT uFlags,
+ UINT FAR *reserved,
+ LPSTR pszName,
+ UINT cchMax )
+{
+ if ( uFlags == GCS_HELPTEXT && _pIdTable != NULL )
+ {
+ ::LoadString( ::hmodNW,
+ IDS_VERBS_HELP_BASE + _pIdTable[idCmd].idResourceString,
+ (LPWSTR) pszName,
+ cchMax );
+
+ return NOERROR;
+ }
+
+ return E_NOTIMPL;
+}
+
+//
+// FUNCTION: CNWFldContextMenu::QueryContextMenu(HMENU, UINT, UINT, UINT, UINT)
+//
+// PURPOSE: Called by the shell just before the context menu is displayed.
+// This is where you add your specific menu items.
+//
+// PARAMETERS:
+// hMenu - Handle to the context menu
+// indexMenu - Index of where to begin inserting menu items
+// idCmdFirst - Lowest value for new menu ID's
+// idCmtLast - Highest value for new menu ID's
+// uFlags - Specifies the context of the menu event
+//
+// RETURN VALUE:
+//
+//
+// COMMENTS:
+//
+
+STDMETHODIMP CNWFldContextMenu::QueryContextMenu( HMENU hMenu,
+ UINT indexMenu,
+ UINT idCmdFirst,
+ UINT idCmdLast,
+ UINT uFlags )
+{
+ UINT idCmd = idCmdFirst;
+
+ if ( IsNetWareObject() )
+ {
+ WCHAR szFullPath[MAX_PATH+1];
+
+ if ( GetFSObject( szFullPath, sizeof( szFullPath )) == NOERROR )
+ {
+ BOOL fUNC = FALSE;
+
+ // Check if the name at least contains the "\\server\share\dir"
+ // We need to add "Map Network Drive" menu in this case.
+ if (( szFullPath[0] == L'\\') && ( szFullPath[1] == L'\\'))
+ {
+ LPWSTR pszLastSlash = wcschr( szFullPath + 2, L'\\');
+ if ( pszLastSlash )
+ pszLastSlash = wcschr( pszLastSlash+1, L'\\');
+
+ if ( pszLastSlash != NULL )
+ fUNC = TRUE;
+ }
+
+ if ( fUNC )
+ {
+ LPNETRESOURCE pNetRes = (LPNETRESOURCE) _buffer;
+ WCHAR szProvider[MAX_PATH+1];
+
+ // Build a net resource that can be used to connect
+
+ // store the provider name first
+ wcscpy( szProvider, pNetRes->lpProvider );
+
+ // zero out the memory cause it is filled by IsNetWareObject
+ RtlZeroMemory( pNetRes, sizeof(NETRESOURCE));
+
+ pNetRes->dwType = RESOURCETYPE_DISK;
+ pNetRes->lpRemoteName = (LPWSTR) ((DWORD)pNetRes + sizeof(NETRESOURCE));
+ wcscpy( pNetRes->lpRemoteName, szFullPath );
+
+ pNetRes->lpProvider = (LPWSTR) ((DWORD)pNetRes->lpRemoteName + (wcslen(szFullPath)+1)*sizeof(WCHAR));
+ wcscpy( pNetRes->lpProvider, szProvider );
+
+ if ( InsertMenu(hMenu, indexMenu, MF_SEPARATOR | MF_BYPOSITION, 0, NULL))
+ {
+ indexMenu++;
+ }
+
+ return InsertCommandsArray( hMenu, indexMenu,
+ idCmdFirst, aDirectoryVerbs );
+ }
+ }
+ }
+
+ // Must return number of menu items we added.
+ // Nothing added here.
+ return ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 0 ));
+
+}
+
+//
+// FUNCTION: CNWFldContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO)
+//
+// PURPOSE: Called by the shell after the user has selected on of the
+// menu items that was added in QueryContextMenu().
+//
+// PARAMETERS:
+// lpcmi - Pointer to an CMINVOKECOMMANDINFO structure
+//
+// RETURN VALUE:
+//
+//
+// COMMENTS:
+//
+
+STDMETHODIMP CNWFldContextMenu::InvokeCommand( LPCMINVOKECOMMANDINFO lpcmi )
+{
+ HRESULT hres = ResultFromScode(E_INVALIDARG);
+ UINT idCmd = LookupCommand( aDirectoryVerbs , lpcmi->lpVerb );
+
+ if ( !idCmd )
+ return hres;
+
+ LPNETRESOURCE pNetRes = (LPNETRESOURCE) _buffer;
+
+ switch ( idCmd )
+ {
+ case IDO_VERB_MAPNETWORKDRIVE:
+ hres = NWUIMapNetworkDrive( lpcmi->hwnd, pNetRes );
+ break;
+ }
+
+ return hres;
+}
+
+
+//
+// FUNCTION: CNWFldContextMenu::GetCommandString( UINT, UINT, UINT FAR *, LPSTR, UINT )
+//
+// PURPOSE: Called by the shell after the user has selected on of the
+// menu items that was added in QueryContextMenu().
+//
+// PARAMETERS:
+//
+// RETURN VALUE:
+//
+//
+// COMMENTS:
+//
+
+STDMETHODIMP CNWFldContextMenu::GetCommandString( UINT idCmd,
+ UINT uFlags,
+ UINT FAR *reserved,
+ LPSTR pszName,
+ UINT cchMax )
+{
+ if ( uFlags == GCS_HELPTEXT )
+ {
+ ::LoadString( ::hmodNW,
+ IDS_VERBS_HELP_BASE + IDO_VERB_MAPNETWORKDRIVE,
+ (LPWSTR) pszName,
+ cchMax );
+
+ return NOERROR;
+ }
+
+ return E_NOTIMPL;
+}
+
+//
+// Method checks if the selected object belongs the netware provider
+//
+BOOL CNWFldContextMenu::IsNetWareObject( VOID )
+{
+ LPNETRESOURCE pNetRes = (LPNETRESOURCE) _buffer;
+
+ if ( !::GetNetResourceFromShell( _pDataObj,
+ pNetRes,
+ sizeof(_buffer)))
+ {
+ // Cannot get the NETRESOURCE of the selected object,
+ // hence assume that the object is not a NetWare object.
+ return FALSE;
+ }
+
+ if ( ( pNetRes->lpProvider != NULL )
+ && ( _wcsicmp( pNetRes->lpProvider, g_szProviderName ) == 0 )
+ )
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//
+// Method obtains file system name associated with selected shell object
+//
+HRESULT CNWFldContextMenu::GetFSObject( LPWSTR pszPath, UINT cbMaxPath )
+{
+ FORMATETC fmte = { CF_HDROP,
+ (DVTARGETDEVICE FAR *) NULL,
+ DVASPECT_CONTENT,
+ -1,
+ TYMED_HGLOBAL };
+
+ STGMEDIUM medium;
+ HRESULT hres = _pDataObj->GetData( &fmte, &medium);
+
+ if (SUCCEEDED(hres))
+ {
+ if ( g_pFuncSHDragQueryFile )
+ {
+ HDROP hdrop = (HDROP) medium.hGlobal;
+ UINT cFiles = (*g_pFuncSHDragQueryFile)( hdrop, (UINT)-1, NULL, 0 );
+
+ (*g_pFuncSHDragQueryFile)( hdrop, 0, pszPath, cbMaxPath );
+
+ ODS(L"CNWFldContextMenu::GetFSObject()\n");
+ ODS( pszPath );
+ ODS(L"\n");
+ }
+
+ //
+ // HACK: We are supposed to call ReleaseStgMedium. This is a temporary
+ // hack until OLE 2.01 for Chicago is released.
+ //
+ if (medium.pUnkForRelease)
+ {
+ medium.pUnkForRelease->Release();
+ }
+ else
+ {
+ GlobalFree(medium.hGlobal);
+ }
+ }
+
+ return hres;
+}
+
+
+// FUNCTION: CNWHoodContextMenu::QueryContextMenu(HMENU, UINT, UINT, UINT, UINT)
+//
+// PURPOSE: Called by the shell just before the context menu is displayed.
+// This is where you add your specific menu items.
+//
+// PARAMETERS:
+// hMenu - Handle to the context menu
+// indexMenu - Index of where to begin inserting menu items
+// idCmdFirst - Lowest value for new menu ID's
+// idCmtLast - Highest value for new menu ID's
+// uFlags - Specifies the context of the menu event
+//
+// RETURN VALUE:
+//
+//
+// COMMENTS:
+//
+
+STDMETHODIMP CNWHoodContextMenu::QueryContextMenu( HMENU hMenu,
+ UINT indexMenu,
+ UINT idCmdFirst,
+ UINT idCmdLast,
+ UINT uFlags )
+{
+ // First, insert a menu separator
+ if ( InsertMenu(hMenu, indexMenu, MF_SEPARATOR | MF_BYPOSITION, 0, NULL))
+ {
+ indexMenu++;
+ }
+
+ // Then, insert the verbs
+ return InsertCommandsArray( hMenu, indexMenu,
+ idCmdFirst, aHoodVerbs );
+}
+
+//
+// FUNCTION: CNWHoodContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO)
+//
+// PURPOSE: Called by the shell after the user has selected on of the
+// menu items that was added in QueryContextMenu().
+//
+// PARAMETERS:
+// lpcmi - Pointer to an CMINVOKECOMMANDINFO structure
+//
+// RETURN VALUE:
+//
+//
+// COMMENTS:
+//
+
+STDMETHODIMP CNWHoodContextMenu::InvokeCommand( LPCMINVOKECOMMANDINFO lpcmi )
+{
+ HRESULT hres = ResultFromScode(E_INVALIDARG);
+ UINT idCmd = LookupCommand( aHoodVerbs , lpcmi->lpVerb );
+
+ if ( !idCmd )
+ return hres;
+
+ switch ( idCmd )
+ {
+ case IDO_VERB_GLOBALWHOAMI:
+ hres = NWUIGlobalWhoAmI( lpcmi->hwnd );
+ break;
+ }
+
+ return hres;
+}
+
+
+//
+// FUNCTION: CNWHoodContextMenu::GetCommandString( UINT, UINT, UINT FAR *, LPSTR, UINT)
+//
+// PURPOSE: Called by the shell after the user has selected on of the
+// menu items that was added in QueryContextMenu().
+//
+// PARAMETERS:
+//
+// RETURN VALUE:
+//
+//
+// COMMENTS:
+//
+
+STDMETHODIMP CNWHoodContextMenu::GetCommandString( UINT idCmd,
+ UINT uFlags,
+ UINT FAR *reserved,
+ LPSTR pszName,
+ UINT cchMax )
+{
+ if ( uFlags == GCS_HELPTEXT )
+ {
+ ::LoadString( ::hmodNW,
+ IDS_VERBS_HELP_BASE + IDO_VERB_GLOBALWHOAMI,
+ (LPWSTR) pszName,
+ cchMax );
+
+ return NOERROR;
+ }
+
+ return E_NOTIMPL;
+}
+
+//
+// Method gets the NETRESOURCE of the selected object
+//
+BOOL GetNetResourceFromShell( LPDATAOBJECT pDataObj,
+ LPNETRESOURCE pNetRes,
+ UINT dwBufferSize )
+{
+ FORMATETC fmte = { g_cfNetResource ? g_cfNetResource
+ : (g_cfNetResource=RegisterClipboardFormat(CFSTR_NETRESOURCES)),
+ (DVTARGETDEVICE FAR *) NULL,
+ DVASPECT_CONTENT,
+ -1,
+ TYMED_HGLOBAL };
+
+ STGMEDIUM medium;
+ UINT cItems;
+
+ if ( pNetRes == NULL )
+ return FALSE;
+
+ memset( pNetRes, 0, dwBufferSize );
+
+ if ( !g_pFuncSHGetNetResource ) // Not loaded
+ return FALSE;
+
+ HRESULT hres = pDataObj->GetData( &fmte, &medium );
+
+ if (!SUCCEEDED(hres))
+ return FALSE;
+
+ HNRES hnres = medium.hGlobal;
+
+ // Get the number of selected items
+ cItems = (*g_pFuncSHGetNetResource)( hnres, (UINT)-1, NULL, 0);
+
+ if ( cItems == 0 ) // Nothing selected
+ return FALSE;
+
+ // Get the NETRESOURCE of the first item
+ (*g_pFuncSHGetNetResource)( hnres, 0, pNetRes, dwBufferSize);
+
+#if DBG
+ WCHAR szTemp[32];
+ wsprintf(szTemp, L"DisplayType = %d\n", pNetRes->dwDisplayType );
+
+ ODS(L"\n**** GetNetResourceFromShell ***\n");
+ ODS(pNetRes->lpProvider );
+ ODS(L"\n");
+ ODS(pNetRes->lpRemoteName );
+ ODS(L"\n");
+ ODS(szTemp );
+ ODS(L"\n\n");
+#endif
+
+ //
+ // HACK: We are supposed to call ReleaseStgMedium. This is a temporary
+ // hack until OLE 2.01 for Chicago is released.
+ //
+ if (medium.pUnkForRelease)
+ {
+ medium.pUnkForRelease->Release();
+ }
+ else
+ {
+ GlobalFree(medium.hGlobal);
+ }
+
+ return TRUE;
+}
+
+//-------------------------------------------------------------------//
+
+HRESULT InsertCommandsArray( HMENU hMenu,
+ UINT indexMenu,
+ UINT idCmdFirst,
+ LPNWMENUITEM aVerbs )
+{
+ UINT idNewCmdFirst = idCmdFirst;
+ WCHAR szVerb[MAX_VERB_SIZE];
+
+ for ( int i = 0; aVerbs[i].idResourceString ; i++)
+ {
+ if ( ::LoadString( ::hmodNW,
+ aVerbs[i].idResourceString + IDS_VERBS_BASE,
+ szVerb,
+ sizeof(szVerb)/sizeof(szVerb[0])))
+ {
+ if (::InsertMenu( hMenu,
+ indexMenu,
+ MF_STRING | MF_BYPOSITION,
+ idNewCmdFirst,
+ szVerb))
+ {
+ // Add command id to the array
+ aVerbs[i].idCommand = idNewCmdFirst;
+
+ // Update command id and index
+ idNewCmdFirst++;
+ if (indexMenu != (UINT)-1)
+ indexMenu++;
+ }
+ }
+ }
+
+ return ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS,
+ FACILITY_NULL,
+ (USHORT)(idNewCmdFirst-idCmdFirst)));
+}
+
+UINT LookupCommand( LPNWMENUITEM aVerbs, LPCSTR pszCmd )
+{
+ if (HIWORD(pszCmd))
+ {
+ // Possible that shell will use string commands, but unlikely
+
+ WCHAR szVerb[MAX_VERB_SIZE];
+ for ( int i=0; aVerbs[i].idResourceString; i++)
+ {
+ if ( ::LoadString( ::hmodNW,
+ aVerbs[i].idResourceString + IDS_VERBS_BASE,
+ szVerb,
+ sizeof(szVerb)/sizeof(szVerb[0])))
+ {
+ if( ::lstrcmpi( (LPCWSTR) pszCmd, szVerb) == 0)
+ return( aVerbs[i].idResourceString);
+ }
+ }
+
+ return 0;
+ }
+ else
+ {
+ return( aVerbs[LOWORD(pszCmd)].idResourceString);
+ }
+}
+
+UINT LookupResource( LPNWMENUITEM aVerbs, UINT uiResourceOffset )
+{
+ for ( int i = 0; aVerbs[i].idResourceString; i++ )
+ {
+ if ( aVerbs[i].idResourceString == uiResourceOffset )
+ return aVerbs[i].idCommand;
+ }
+
+ return 0;
+}
+
+//-------------------------------------------------------------------//
+
+#define _ILSkip(pidl, cb) ((LPITEMIDLIST)(((BYTE*)(pidl))+cb))
+#define _ILNext(pidl) _ILSkip(pidl, (pidl)->mkid.cb)
+
+#define HIDA_GetPIDLFolder(pida) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[0])
+#define HIDA_GetPIDLItem(pida, i) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[i+1])
+
+static
+UINT WINAPI MyILGetSize(LPCITEMIDLIST pidl)
+{
+ UINT cbTotal = 0;
+ if (pidl)
+ {
+ cbTotal += sizeof(pidl->mkid.cb); // Null terminator
+ while (pidl->mkid.cb)
+ {
+ cbTotal += pidl->mkid.cb;
+ pidl = _ILNext(pidl);
+ }
+ }
+
+ return cbTotal;
+}
+
+UINT WINAPI HIDA_GetIDList( LPIDA hida, UINT i, LPITEMIDLIST pidlOut, UINT cbMax)
+{
+ LPCITEMIDLIST pidlFolder = HIDA_GetPIDLFolder((LPIDA)hida);
+ LPCITEMIDLIST pidlItem = HIDA_GetPIDLItem((LPIDA)hida, i);
+
+ UINT cbFolder = MyILGetSize(pidlFolder)-sizeof(USHORT);
+ UINT cbItem = MyILGetSize(pidlItem);
+
+ if (cbMax < cbFolder+cbItem)
+ {
+ if (pidlOut)
+ pidlOut->mkid.cb = 0;
+ }
+ else
+ {
+ memmove(pidlOut, pidlFolder, cbFolder);
+ memmove(((LPBYTE)pidlOut)+cbFolder, pidlItem, cbItem);
+ }
+
+ return (cbFolder+cbItem);
+}