Shell Properties Pages

Robert Shearman R.J.Shearman at warwick.ac.uk
Sat Jan 11 19:58:16 CST 2003


Hi,

This is the start of an implementation of property pages. The version page
is pretty much complete, but the general page is only just starting.

ChangeLog:
- Allow user to view the properties of an file system object

Rob
-------------- next part --------------
Index: wine/dlls/shell32/shlexec.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shlexec.c,v
retrieving revision 1.16
diff -u -r1.16 shlexec.c
--- wine/dlls/shell32/shlexec.c	3 Jan 2003 03:03:36 -0000	1.16
+++ wine/dlls/shell32/shlexec.c	11 Jan 2003 21:07:18 -0000
@@ -40,10 +40,12 @@
 #include "shlobj.h"
 #include "shlwapi.h"
 #include "ddeml.h"
+#include "winver.h"
 
 #include "wine/winbase16.h"
 #include "shell32_main.h"
 #include "undocshell.h"
+#include "shresdef.h"
 
 #include "wine/debug.h"
 
@@ -543,6 +545,8 @@
     return (HINSTANCE)31;    /* default - 'No association was found' */
 }
 
+HWND SHELL_ExecuteProperties(SHELLEXECUTEINFOA * sei);
+
 /*************************************************************************
  *	ShellExecuteExA32 [Internal]
  */
@@ -648,6 +652,12 @@
         strcat(szApplicationName, szCommandline);
     }
 
+    if (!StrCmpIA(lpOperation, "properties"))
+    {
+        retval = (UINT)SHELL_ExecuteProperties(sei);
+	return TRUE;
+    }
+
     retval = execfunc(szApplicationName, sei, FALSE);
     if (retval > 32)
         return TRUE;
@@ -836,4 +846,310 @@
 
     ShellExecuteExW (&sei);
     return sei.hInstApp;
+}
+
+BOOL CALLBACK GeneralDialogProc(HWND hWndDialog, UINT uMsg, WPARAM wParam, LPARAM lParam);
+static HPROPSHEETPAGE CreateVersionPage(LPWSTR szPath);
+
+HWND SHELL_ExecuteProperties(SHELLEXECUTEINFOA * sei)
+{
+    PROPSHEETPAGEW psp; /* move to general create proc */
+    PROPSHEETHEADERW psh;
+    HWND hWndProp;
+    LPWSTR wszPath;
+    WCHAR wszCaption[1024]; /* max len of wsprintf string*/
+    WCHAR wszCaptionFormat[MAX_PATH + 1];
+    HPROPSHEETPAGE hPsp[2]; /* FIXME: create dynamically */
+
+    wszPath = HeapAlloc(GetProcessHeap(), 0, (lstrlenA(sei->lpFile)+1)*sizeof(WCHAR));
+    MultiByteToWideChar(CP_ACP, 0, sei->lpFile, -1, wszPath, -1);
+    LoadStringW(shell32_hInstance, IDS_SHELL_PROPERTIES, wszCaptionFormat, MAX_PATH);
+    wsprintfW(wszCaption, wszCaptionFormat, wszPath);
+
+    psp.dwSize = sizeof(PROPSHEETPAGEW);
+    psp.dwFlags = PSP_DEFAULT;
+    psp.hInstance = shell32_hInstance;
+    psp.u.pszTemplate = MAKEINTRESOURCEW(IDD_SHELL_GENERAL_SHEET);
+    psp.u2.pszIcon = NULL;
+    psp.pfnDlgProc = GeneralDialogProc;
+    psp.pszTitle = NULL;
+    psp.lParam = (LPARAM)wszPath;
+    psp.pfnCallback = NULL;
+
+    hPsp[0] = CreatePropertySheetPageW(&psp);
+    hPsp[1] = CreateVersionPage(wszPath);
+
+    psh.dwSize = sizeof(PROPSHEETHEADERW);
+    psh.dwFlags = PSH_DEFAULT;
+    psh.hwndParent = sei->hwnd;
+    psh.hInstance = shell32_hInstance;
+    psh.u.pszIcon = NULL;
+    psh.pszCaption = wszCaption;
+    psh.nPages = 2;
+    psh.u2.nStartPage = 0;
+    psh.u3.phpage = hPsp;
+    psh.pfnCallback = NULL;
+
+    hWndProp = (HWND)PropertySheetW(&psh);
+
+    return hWndProp;
+}
+
+BOOL CALLBACK GeneralDialogProc(HWND hWndDialog, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    static PROPSHEETPAGEW * pPsp = NULL;
+    switch (uMsg)
+    {
+        case WM_INITDIALOG:
+	{
+	    SHFILEINFOW shfi;
+	    pPsp = (PROPSHEETPAGEW *)lParam;
+            SHGetFileInfoW((LPWSTR)pPsp->lParam, 0, &shfi, sizeof(SHFILEINFOW), SHGFI_DISPLAYNAME | SHGFI_ICON | SHGFI_LARGEICON | SHGFI_TYPENAME);
+	    SendMessageW(GetDlgItem(hWndDialog, 12298), WM_SETTEXT, 0, (LPARAM)shfi.szDisplayName);
+	    SendMessageW(GetDlgItem(hWndDialog, 12297), STM_SETIMAGE, IMAGE_ICON, (LPARAM)shfi.hIcon);
+	    if (lstrlenW(shfi.szTypeName) == 0)
+	    {
+	        WCHAR buffer[1024]; /* sprintf limit */
+		WCHAR format[128];
+		LPWSTR extension = PathFindExtensionW((LPWSTR)pPsp->lParam);
+		if (extension)
+		{
+			LoadStringW(shell32_hInstance, IDS_SHELL_TYPEFORMAT, format, sizeof(format) / sizeof(*format) - 1);
+			wsprintfW(buffer, format, extension+1 /* remove '.' from front */);
+			SendMessageW(GetDlgItem(hWndDialog, 12296), WM_SETTEXT, 0, (LPARAM)buffer);
+		}
+	    }
+	    else
+	        SendMessageW(GetDlgItem(hWndDialog, 12296), WM_SETTEXT, 0, (LPARAM)shfi.szTypeName);
+
+	    return TRUE;
+        }
+        case WM_DESTROY:
+	    HeapFree(GetProcessHeap(), 0, (LPWSTR)pPsp->lParam);
+	    pPsp->lParam = 0;
+	    break;
+        default:
+            return FALSE;
+    }
+    return TRUE;
+}
+
+/* copied from dlls/version/info.c */
+#define DWORD_ALIGN( base, ptr ) \
+    ( (LPBYTE)(base) + ((((LPBYTE)(ptr) - (LPBYTE)(base)) + 3) & ~3) )
+#define VersionInfo32_Value( ver )  \
+    DWORD_ALIGN( (ver), (ver)->szKey + lstrlenW((ver)->szKey) + 1 )
+#define VersionInfo32_Children( ver )  \
+    ( VersionInfo32_Value( ver ) + \
+    ( ( (ver)->wValueLength * \
+    ((ver)->bText? 2 : 1) + 3 ) & ~3 ) )
+
+typedef struct {
+    WORD   wLength;
+    WORD   wValueLength;
+    WORD   wType;
+    WCHAR  szKey[1];
+#if 0 /* not real members (see VersionInfo32_Value macro)*/
+    WORD   Padding[];
+    WORD   Value[];
+#endif
+} VerString;
+
+typedef struct {
+    WORD        wLength;
+    WORD        wValueLength;
+    WORD        bText;
+    WCHAR       szKey[1];
+#if 0
+    WORD        Padding[];
+    StringTable Children[];
+#endif
+} StringFileInfo;
+
+UINT DWORD_ALIGN2(UINT value)
+{
+	if (value % 4 != 0)
+		value += 4 - value % 4;
+	return value;
+}
+
+typedef struct
+{
+	LPWSTR szPath;
+	LPVOID pBlock;
+	LPWSTR pszLanguages;
+} VerDlgData;
+
+static LRESULT VersionAddEntry(HWND hwndDlg, LPWSTR szKey, LPCWSTR szValue)
+{
+    UINT iItem = (UINT)SendMessageW(GetDlgItem(hwndDlg, 1005), LB_ADDSTRING, 0, (LPARAM)szKey);
+	return SendMessageW(GetDlgItem(hwndDlg, 1005), LB_SETITEMDATA, iItem, (LPARAM)szValue);
+}
+
+/* Parse version resources and fill in controls on property sheet */
+static void VersionDialogInit(HWND hwnd, VerDlgData * dlgData)
+{
+	WCHAR SubBlock[MAX_PATH];
+	WCHAR wcszTranslate[] = {'\\','V','a','r','F','i','l','e','I','n','f','o','\\',
+		                     'T','r','a','n','s','l','a','t','i','o','n',0};
+	WCHAR wcszSFI[] = {'\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o',0};
+	WCHAR wcszSlash[] = {'\\',0};
+	WCHAR wcszComma[] = {',',' ',0};
+
+	/* FIXME: get from string resources */
+	WCHAR wcszLanguage[] = {'L','a','n','g','u','a','g','e',0};
+	WCHAR wcszLanguages[] = {'L','a','n','g','u','a','g','e','s',0};
+	/*-- END FIXME --*/
+
+	WCHAR wcszVarFileInfo[] = {'V','a','r','F','i','l','e','I','n','f','o',0};
+	WCHAR wcszFileDesc[] = {'F','i','l','e','D','e','s','c','r','i','p','t','i','o','n',0};
+	WCHAR wcszFileVer[] = {'F','i','l','e','V','e','r','s','i','o','n',0};
+	WCHAR wcszCopyright[] = {'L','e','g','a','l','C','o','p','y','r','i','g','h','t',0};
+
+	UINT nTranslations; /* number of languages present */
+	UINT i;
+	UINT dwBytes;
+	VerString * pVerString;
+	StringFileInfo * pStringFileInfo;
+
+	/* Structure used to store enumerated languages and code pages
+	 * This is documented on MSDN with the VerQueryValue function, but
+	 * is not defined anywhere in the official headers */
+	struct LANGANDCODEPAGE
+	{
+	  WORD wLanguage;
+	  WORD wCodePage;
+	} *lpTranslate;
+
+	/* Get the size of the resource block and fail if no version info available */
+	DWORD blocksize = GetFileVersionInfoSizeW(dlgData->szPath, NULL);
+	dlgData->pBlock = HeapAlloc(GetProcessHeap(), 0, blocksize);
+	dlgData->pszLanguages = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (MAX_PATH + 1) * sizeof(WCHAR));
+
+	/* GetFileVersionInfo copies the resource block into pBlock for us to use in all the
+	 * later functions */
+	if (!blocksize || !GetFileVersionInfoW(dlgData->szPath, 0, blocksize, dlgData->pBlock))
+		return; /* no file version available */
+
+	/* Read the list of languages (and code pages) */
+	VerQueryValueW(dlgData->pBlock,
+				  wcszTranslate,
+				  (LPVOID*)&lpTranslate,
+				  &nTranslations);
+	nTranslations /= sizeof(struct LANGANDCODEPAGE);
+
+
+	/* Get all the languages defined and convert them to a readable string */
+	*dlgData->pszLanguages = '\0';
+	for(i = 0; i < nTranslations; i++)
+	{
+		if (!VerQueryValueW(dlgData->pBlock,
+                            wcszSFI,
+					        (LPVOID *)&pStringFileInfo,
+					        &dwBytes))
+			return;
+		VerLanguageNameW(lpTranslate[i].wLanguage, SubBlock, MAX_PATH);
+		if (lstrlenW(dlgData->pszLanguages))
+		{
+			StrCatW(dlgData->pszLanguages, wcszComma);
+		}
+		StrCatW(dlgData->pszLanguages, SubBlock);
+	}
+	VersionAddEntry(hwnd, nTranslations > 1 ? wcszLanguages : wcszLanguage, dlgData->pszLanguages);
+
+	/* FIXME: we use first language defined. Is this right? */
+	StrCpyW(SubBlock, wcszSFI);
+	StrCatW(SubBlock, wcszSlash);
+	StrCatW(SubBlock, pStringFileInfo->szKey);
+	if (!VerQueryValueW(dlgData->pBlock,
+					    SubBlock,
+					    (LPVOID *)&pVerString,
+					    &dwBytes))
+		return;
+
+	dwBytes = (WORD)(int)VersionInfo32_Children(pStringFileInfo); /* get the real(!) size of the block from here */
+	for (; (DWORD)pVerString < (DWORD)pStringFileInfo + dwBytes; pVerString = (VerString *)(((LPBYTE)pVerString)+DWORD_ALIGN2(pVerString->wLength)))
+	{
+		if (!StrCmpW(wcszVarFileInfo, pVerString->szKey)) /* FIXME: this is a hack to stop unwanted information appearing (dwBytes wrong???)*/
+			break;
+		else
+		{
+			if (!StrCmpW(wcszFileDesc, pVerString->szKey))
+				SendMessageW(GetDlgItem(hwnd, 1001), WM_SETTEXT, 0, (LPARAM)(pVerString->wValueLength > 0 ? VersionInfo32_Value(pVerString) : 0));
+			else if (!StrCmpW(wcszFileVer, pVerString->szKey))
+				SendMessageW(GetDlgItem(hwnd, 1000), WM_SETTEXT, 0, (LPARAM)(pVerString->wValueLength > 0 ? VersionInfo32_Value(pVerString) : 0));
+			else if (!StrCmpW(wcszCopyright, pVerString->szKey))
+				SendMessageW(GetDlgItem(hwnd, 1002), WM_SETTEXT, 0, (LPARAM)(pVerString->wValueLength > 0 ? VersionInfo32_Value(pVerString) : 0));
+			else
+			{
+				/* FIXME: pretify the known key names */
+
+				/* Add entry to list, making sure we don't copy a load of rubbish to the text box
+				 * from wValueLength == 0, but value not pointing to an empty string, just the start
+				 * of the next item */
+				if (isalpha((char)*pVerString->szKey)) /* FIXME: this is a hack to stop unwanted information appearing */
+					VersionAddEntry(hwnd, pVerString->szKey, pVerString->wValueLength > 0 ? (LPWSTR)VersionInfo32_Value(pVerString) : 0);
+			}
+		}
+	}
+	return;
+}
+
+static BOOL WINAPI VersionDialogProc(HWND hwndDialog, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+	if (uMsg == WM_INITDIALOG)
+	{
+		VersionDialogInit(hwndDialog, (VerDlgData *)((LPPROPSHEETPAGEW)(lParam))->lParam);
+		SendMessageW(GetDlgItem(hwndDialog, 1005), LB_SETCURSEL, 0, 0);
+		SendMessageW(GetDlgItem(hwndDialog, 1004), WM_SETTEXT, 0, SendMessageW(GetDlgItem(hwndDialog, 1005), LB_GETITEMDATA, 0, 0));
+		return TRUE;
+	}
+	if ((uMsg == WM_COMMAND) && (HIWORD(wParam) == LBN_SELCHANGE))
+	{
+		UINT nCurSel = SendMessageW((HWND)lParam, LB_GETCURSEL, 0, 0);
+		SendMessageW(GetDlgItem(hwndDialog, 1004), WM_SETTEXT, 0, SendMessageW((HWND)lParam, LB_GETITEMDATA, nCurSel, 0));
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/* Heap freeing calls put here as WM_DESTROY seems to be called when we don't want it
+ * in VersionDialogProc */
+static UINT CALLBACK VersionDialogCallback(HWND hwnd, UINT uMsg, LPPROPSHEETPAGEW pPsp)
+{
+	if (uMsg == PSPCB_CREATE)
+	{
+		return TRUE;
+	}
+	if (uMsg == PSPCB_RELEASE)
+	{
+		VerDlgData * dlgData = (VerDlgData*)pPsp->lParam;
+		if (dlgData)
+		{
+			HeapFree(GetProcessHeap(), 0, dlgData->szPath);
+			HeapFree(GetProcessHeap(), 0, dlgData->pBlock);
+			HeapFree(GetProcessHeap(), 0, dlgData->pszLanguages);
+			HeapFree(GetProcessHeap(), 0, dlgData);
+			pPsp->lParam = 0;
+		}
+	}
+	return FALSE;
+}
+
+/* Create the version property sheet */
+static HPROPSHEETPAGE CreateVersionPage(LPWSTR szPath)
+{
+	PROPSHEETPAGEW psp;
+	VerDlgData * pDlgData = (VerDlgData *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(VerDlgData));
+	pDlgData->szPath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (lstrlenW(szPath) + 1) * sizeof(WCHAR));
+	StrCpyW(pDlgData->szPath, szPath);
+
+	psp.dwSize = sizeof(PROPSHEETPAGEW);
+	psp.dwFlags = PSP_DEFAULT | PSP_USECALLBACK;
+	psp.hInstance = shell32_hInstance;
+	psp.u.pszTemplate = (LPCWSTR)400;
+	psp.lParam = (LPARAM)pDlgData;
+	psp.pfnDlgProc = VersionDialogProc;
+	psp.pfnCallback = VersionDialogCallback;
+	return CreatePropertySheetPageW(&psp);
 }
Index: wine/dlls/shell32/shlfolder.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shlfolder.c,v
retrieving revision 1.76
diff -u -r1.76 shlfolder.c
--- wine/dlls/shell32/shlfolder.c	5 Dec 2002 20:33:08 -0000	1.76
+++ wine/dlls/shell32/shlfolder.c	11 Jan 2003 21:07:19 -0000
@@ -298,6 +298,9 @@
 	    STRRET strTemp;
 	    LPITEMIDLIST pidlNext = ILGetNext (pidl);
 
+	    // since we are dealing with ANSI strings anyway
+	    strTemp.uType = STRRET_CSTR;
+
 	    hr = IShellFolder_GetDisplayNameOf (psfChild, pidlNext, dwFlags, &strTemp);
 	    if (SUCCEEDED (hr)) {
 		hr = StrRetToStrNA (szOut, dwOutLen, &strTemp, pidlNext);
Index: wine/dlls/shell32/shres.rc
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shres.rc,v
retrieving revision 1.27
diff -u -r1.27 shres.rc
--- wine/dlls/shell32/shres.rc	19 Dec 2002 04:11:22 -0000	1.27
+++ wine/dlls/shell32/shres.rc	11 Jan 2003 21:07:21 -0000
@@ -156,6 +156,45 @@
 	IDS_OVERWRITEFILE_CAPTION "Confirm File OverWrite"
 }
 
+/* resources for file property sheet */
+STRINGTABLE DISCARDABLE
+{
+	IDS_SHELL_PROPERTIES "%s properties" /* caption for properties dialog */
+	IDS_SHELL_TYPEFORMAT "%s file" /* format of type name general property */
+}
+
+IDD_SHELL_GENERAL_SHEET DIALOG DISCARDABLE 0, 0, 227, 210
+STYLE DS_NOIDLEMSG | DS_3DLOOK | WS_CHILD | WS_CAPTION
+CAPTION "General"
+FONT 8,"Helv"
+{
+ ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE
+ EDITTEXT 12298,48,15,78,12,ES_AUTOHSCROLL
+/* LTEXT "Filename",12305,7,13,37,15 */
+ LTEXT "<unknown type>", 12296,48,27,78,25
+}
+
+400 DIALOG DISCARDABLE  0, 0, 227, 210
+STYLE DS_NOIDLEMSG | DS_3DLOOK | WS_CHILD | WS_CAPTION
+CAPTION "Version"
+FONT 8, "MS Shell Dlg"
+BEGIN
+    GROUPBOX        "Other version information",1203,8,65,211,122
+    EDITTEXT        1000,61,8,133,13,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+    EDITTEXT        1001,61,26,133,13,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+    EDITTEXT        1002,61,44,133,13,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+    LTEXT           "File version:",1200,12,8,49,9
+    LTEXT           "Description:",1201,12,25,49,9
+    LTEXT           "Copyright:",1202,12,44,49,9
+    EDITTEXT        1004,113,90,97,89,ES_MULTILINE | ES_READONLY |
+                    WS_VSCROLL
+    LTEXT           "Item name:",1204,20,79,40,9
+    LTEXT           "Value:",1205,113,78,41,9
+    LISTBOX         1005,16,90,91,89,LBS_SORT | LBS_NOINTEGRALHEIGHT |
+                    WS_VSCROLL | WS_TABSTOP
+END
+
+
 shv_accel ACCELERATORS
 BEGIN
 	VK_F5, FCIDM_SHVIEW_REFRESH, VIRTKEY
Index: wine/dlls/shell32/shresdef.h
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shresdef.h,v
retrieving revision 1.10
diff -u -r1.10 shresdef.h
--- wine/dlls/shell32/shresdef.h	19 Dec 2002 04:11:22 -0000	1.10
+++ wine/dlls/shell32/shresdef.h	11 Jan 2003 21:07:21 -0000
@@ -49,6 +49,10 @@
 #define IDS_OVERWRITEFILE_CAPTION 36
 #define IDS_OVERWRITEFILE_TEXT	37
 
+#define IDS_SHELL_PROPERTIES    38
+#define IDS_SHELL_TYPEFORMAT    39
+#define IDD_SHELL_GENERAL_SHEET 0x3744
+
 /* browse for folder dialog box */
 #define IDD_STATUS		0x3743
 #define IDD_TITLE		0x3742
Index: wine/dlls/shell32/shv_bg_cmenu.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shv_bg_cmenu.c,v
retrieving revision 1.24
diff -u -r1.24 shv_bg_cmenu.c
--- wine/dlls/shell32/shv_bg_cmenu.c	7 Jan 2003 20:36:24 -0000	1.24
+++ wine/dlls/shell32/shv_bg_cmenu.c	11 Jan 2003 21:07:21 -0000
@@ -94,7 +94,7 @@
 	  TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
 	  return S_OK;
 	}
-	TRACE("-- Interface: E_NOINTERFACE\n");
+	ERR("-- Interface: %s - E_NOINTERFACE\n", debugstr_guid(riid));
 	return E_NOINTERFACE;
 }
 
Index: wine/dlls/shell32/shv_item_cmenu.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shv_item_cmenu.c,v
retrieving revision 1.15
diff -u -r1.15 shv_item_cmenu.c
--- wine/dlls/shell32/shv_item_cmenu.c	7 Jan 2003 20:36:24 -0000	1.15
+++ wine/dlls/shell32/shv_item_cmenu.c	11 Jan 2003 21:07:21 -0000
@@ -220,8 +220,6 @@
 
 	TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",This, hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
 
-	if(!(CMF_DEFAULTONLY & uFlags))
-	{
 	  if(uFlags & CMF_EXPLORE)
 	  {
 	    if(This->bAllValues)
@@ -237,7 +235,7 @@
 	  }
 	  else
 	  {
-	    _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_OPEN, MFT_STRING, "&Select", MFS_ENABLED|MFS_DEFAULT);
+	    _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_OPEN, MFT_STRING, "&Open", MFS_ENABLED|MFS_DEFAULT);
 	  }
 	  _InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
 	  _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_COPY, MFT_STRING, "&Copy", MFS_ENABLED);
@@ -249,9 +247,9 @@
 	  if(uFlags & CMF_CANRENAME)
 	    _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_RENAME, MFT_STRING, "&Rename", ISvItemCm_CanRenameItems(This) ? MFS_ENABLED : MFS_DISABLED);
 
-	  return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (FCIDM_SHVIEWLAST));
-	}
-	return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);
+	  _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_PROPERTIES, MFT_STRING, "P&roperties", MFS_ENABLED);
+
+	  return MAKE_HRESULT(SEVERITY_SUCCESS, 0, FCIDM_SHVIEWLAST);
 }
 
 /**************************************************************************
@@ -439,6 +437,9 @@
 	    break;
 	  case FCIDM_SHVIEW_OPEN:
 	    DoOpenExplore(iface, lpcmi->hwnd, "open");
+	    break;
+	  case FCIDM_SHVIEW_PROPERTIES:
+	    DoOpenExplore(iface, lpcmi->hwnd, "properties");
 	    break;
 	  case FCIDM_SHVIEW_RENAME:
 	    DoRename(iface, lpcmi->hwnd);
Index: wine/dlls/shell32/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/shell32/Makefile.in,v
retrieving revision 1.59
diff -u -r1.59 Makefile.in
--- wine/dlls/shell32/Makefile.in	9 Jan 2003 00:03:53 -0000	1.59
+++ wine/dlls/shell32/Makefile.in	11 Jan 2003 21:07:12 -0000
@@ -5,7 +5,7 @@
 VPATH     = @srcdir@
 MODULE    = shell32.dll
 # fixme: avoid ole32.dll import
-IMPORTS   = ole32 shlwapi comctl32 user32 gdi32 advapi32 kernel32
+IMPORTS   = ole32 shlwapi comctl32 user32 gdi32 advapi32 kernel32 version
 ALTNAMES  = shell.dll
 EXTRALIBS = $(LIBUUID) $(LIBUNICODE)
 


More information about the wine-patches mailing list