Shell32 Property Dialogs

Johannes Anderwald johannes.anderwald at student.tugraz.at
Thu Dec 15 03:56:27 CST 2005


This patch adds the file general, file version and shortcut property 
dialog to shell32
modified files: shell32_En.rc - added resources
                      shv_item_cmenu.c - added handling of 
FCIDM_SHVIEW_PROPERTIES verb
                      shell32_main.h - declared dialog callback functions
                      shellink.h - added property verb and handling of 
it - use existing _InsertMenuItem function for that

Name: Johannes Anderwald

-- 
Johannes Anderwald
-------------- next part --------------
Index: dlls/shell32/shell32_En.rc
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shell32_En.rc,v
retrieving revision 1.21
diff -u -r1.21 shell32_En.rc
--- dlls/shell32/shell32_En.rc	6 May 2005 15:44:32 -0000	1.21
+++ dlls/shell32/shell32_En.rc	15 Dec 2005 09:41:22 -0000
@@ -131,6 +131,77 @@
  PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP
 }
 
+SHELL_FILE_GENERAL_DLG DIALOGEX 0, 0, 240, 130
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "General"
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+{
+ ICON "", 14000, 10, 5, 30, 30, WS_VISIBLE
+ EDITTEXT 14001, 70, 5, 100, 10, ES_LEFT | ES_READONLY
+ LTEXT "Type of file:", 14004, 10, 30, 50, 10
+ LTEXT "%s File", 14005, 70, 30, 150, 10
+ LTEXT "Opens with:", 14006, 10, 40, 50, 10
+ LTEXT "", 14007, 70, 40, 150, 10
+ LTEXT "Location:", 14008, 10, 55, 45, 10
+ LTEXT "", 14009, 70, 55, 200, 10
+ LTEXT "Size:",14010, 10, 65, 45, 10
+ LTEXT "", 14011, 70, 65, 150, 10
+ LTEXT "Created:", 14014, 10, 80, 45, 10
+ LTEXT "", 14015, 70, 80, 150, 10
+ LTEXT "Modied:", 14016, 10, 90, 45, 10
+ LTEXT "", 14017, 70, 90, 150, 10
+ LTEXT "Accessed:", 14018, 10, 100, 45, 10
+ LTEXT "", 14019, 70, 100, 150, 10
+ LTEXT "Attributes:", 14020, 10, 115, 45, 10
+ CHECKBOX "&Read-only", 14021, 70, 115, 45, 10
+ CHECKBOX "&Hidden", 14022, 130, 115, 50, 10
+ CHECKBOX "&Archive", 14023, 180, 115, 45, 10
+}
+
+SHELL_FILE_VERSION_DLG DIALOGEX 0, 0, 240, 130
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Version"
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+{
+  LTEXT "File version: ", 14000, 10, 10, 45, 10
+  LTEXT "", 14001, 70, 10, 150, 10
+  LTEXT "Description: ", 14002, 10, 20, 45, 10
+  LTEXT "", 14003, 70, 20, 150, 10
+  LTEXT "Copyright: ", 14004, 10, 30, 45, 10
+  LTEXT "", 14005, 70, 30, 150, 10
+  GROUPBOX "Other version information: ", 14006, 10, 45, 220, 90
+  LTEXT "Item name: ", 14007, 20, 55, 50, 10
+  LTEXT "Value: ", 14008, 130, 55, 45, 10
+  LISTBOX 14009,20,65,95,60, LBS_STANDARD | WS_TABSTOP | LBS_NOTIFY
+  EDITTEXT 14010, 130, 65, 95, 60, ES_LEFT|WS_BORDER|WS_VSCROLL|WS_GROUP|ES_MULTILINE|ES_READONLY
+
+}
+
+SHELL_FILE_SHORTCUT_DLG DIALOGEX 0, 0, 240, 130
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Shortcut"
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+{
+ ICON "", 14000, 10, 5, 30, 30, WS_VISIBLE
+ LTEXT "Target type:", 14004, 10, 30, 50, 10
+ LTEXT "", 14005, 70, 30, 150, 10
+ LTEXT "Target location:", 14006, 10, 40, 70, 10
+ LTEXT "", 14007, 70, 40, 150, 10
+ LTEXT "Target:", 14008, 10, 55, 45, 10
+ EDITTEXT 14009, 70, 55, 150, 10, ES_LEFT
+ LTEXT "&Start in:",14010, 10, 65, 45, 10
+ EDITTEXT 14011, 70, 65, 150, 10, ES_LEFT
+ LTEXT "Shortcut &key:", 14014, 10, 80, 45, 10
+ EDITTEXT 14015, 70, 80, 150, 10, ES_LEFT
+ LTEXT "Run:", 14016, 10, 90, 45, 10
+ EDITTEXT 14017, 70, 90, 150, 10
+ LTEXT "C&omment:", 14018, 10, 100, 45, 10
+ EDITTEXT 14019, 70, 100, 150, 10, ES_LEFT
+ PUSHBUTTON "&Find Target...", 14020, 10, 115, 60, 14, ES_LEFT
+ PUSHBUTTON "&Change Icon...", 14021, 80, 115, 60, 14, ES_LEFT
+ PUSHBUTTON "A&dvanced...", 14022, 150, 115, 60, 14, ES_LEFT
+}
+
 STRINGTABLE DISCARDABLE
 {
         /* columns in the shellview */
Index: dlls/shell32/shell32_main.h
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shell32_main.h,v
retrieving revision 1.110
diff -u -r1.110 shell32_main.h
--- dlls/shell32/shell32_main.h	28 Nov 2005 11:04:35 -0000	1.110
+++ dlls/shell32/shell32_main.h	15 Dec 2005 09:41:22 -0000
@@ -234,4 +234,11 @@
 /* Detect Shell Links */
 BOOL SHELL_IsShortcut(LPCITEMIDLIST);
 
+/* Shell Object Property Dialogs */
+#define MAX_PROPERTY_SHEET_PAGE    32
+INT_PTR CALLBACK SH_FileGeneralDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK SH_FileVersionDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+HPROPSHEETPAGE SH_CreatePropertySheetPage(LPSTR resname, DLGPROC dlgproc, LPFNPSPCALLBACKW pfnCallback, LPARAM lParam);
+
+
 #endif
Index: dlls/shell32/shelllink.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shelllink.c,v
retrieving revision 1.114
diff -u -r1.114 shelllink.c
--- dlls/shell32/shelllink.c	10 Nov 2005 12:14:58 -0000	1.114
+++ dlls/shell32/shelllink.c	15 Dec 2005 09:41:23 -0000
@@ -160,6 +160,7 @@
 
 	BOOL          bDirty;
         INT           iIdOpen;  /* id of the "Open" entry in the context menu */
+        INT           iIdProperties; /* id of the "Properties" entry in the context menu */
 	IUnknown      *site;
 } IShellLinkImpl;
 
@@ -1213,6 +1214,7 @@
 	sl->iShowCmd = SW_SHOWNORMAL;
 	sl->bDirty = FALSE;
 	sl->iIdOpen = -1;
+	sl->iIdProperties = -1;
 	sl->site = NULL;
 
 	TRACE("(%p)->()\n",sl);
@@ -2440,8 +2442,6 @@
                             UINT idCmdFirst, UINT idCmdLast, UINT uFlags )
 {
     IShellLinkImpl *This = impl_from_IContextMenu(iface);
-    static const WCHAR szOpen[] = { 'O','p','e','n',0 };
-    MENUITEMINFOW mii;
     int id = 1;
 
     TRACE("%p %p %u %u %u %u\n", This,
@@ -2450,17 +2450,11 @@
     if ( !hmenu )
         return E_INVALIDARG;
 
-    memset( &mii, 0, sizeof mii );
-    mii.cbSize = sizeof mii;
-    mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
-    mii.dwTypeData = (LPWSTR)szOpen;
-    mii.cch = strlenW( mii.dwTypeData );
-    mii.wID = idCmdFirst + id++;
-    mii.fState = MFS_DEFAULT | MFS_ENABLED;
-    mii.fType = MFT_STRING;
-    if (!InsertMenuItemW( hmenu, indexMenu, TRUE, &mii ))
-        return E_FAIL;
-    This->iIdOpen = 0;
+    This->iIdOpen = id++ + idCmdFirst;
+	_InsertMenuItem(hmenu, indexMenu++, TRUE, This->iIdOpen, MFT_STRING, "&Open", MFS_ENABLED);
+
+	This->iIdProperties = id++ + idCmdFirst;
+	_InsertMenuItem(hmenu, indexMenu++, TRUE, This->iIdProperties, MFT_STRING, "&Properties", MFS_ENABLED);
 
     return MAKE_HRESULT( SEVERITY_SUCCESS, 0, id );
 }
@@ -2489,6 +2483,106 @@
     return path;
 }
 
+
+/**************************************************************************
+ * SH_ShellLinkDlgProc
+ *
+ * dialog proc of the shortcut property dialog
+ */
+
+INT_PTR 
+CALLBACK 
+SH_ShellLinkDlgProc(   
+    HWND hwndDlg,
+    UINT uMsg,
+    WPARAM wParam,
+    LPARAM lParam
+)
+{
+    LPPROPSHEETPAGEW ppsp;
+    IShellLinkImpl *This;
+    HWND hDlgCtrl;
+    switch(uMsg)
+    {
+    case WM_INITDIALOG:
+        ppsp = (LPPROPSHEETPAGEW)lParam;
+        if (ppsp == NULL)
+            break;
+     
+        TRACE("ShellLink_DlgProc (WM_INITDIALOG hwnd %p lParam %p ppsplParam %x)\n",hwndDlg, lParam, ppsp->lParam);
+
+        This = (IShellLinkImpl *)ppsp->lParam;
+
+        if ( This == NULL )
+            break;
+
+		TRACE("sArgs: %S sComponent: %S sDescription: %S sIcoPath: %S sPath: %S sPathRel: %S sProduct: %S sWorkDir: %S\n", This->sArgs, This->sComponent ,This->sDescription,
+			This->sIcoPath, This->sPath, This->sPathRel, This->sProduct, This->sWorkDir);
+
+        /* target path */
+        hDlgCtrl = GetDlgItem( hwndDlg, 14009 );
+        if ( hDlgCtrl != NULL )
+            SendMessageW( hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)This->sPath );
+
+       /* working dir */
+       hDlgCtrl = GetDlgItem( hwndDlg, 14011 );
+       if ( hDlgCtrl != NULL )
+            SendMessageW( hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)This->sWorkDir );
+
+	   /* description */
+       hDlgCtrl = GetDlgItem( hwndDlg, 14019 );
+       if ( hDlgCtrl != NULL )
+            SendMessageW( hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)This->sDescription );
+        return TRUE;
+    default:
+        break;
+   }
+   return FALSE;
+}
+
+/**************************************************************************
+ * ShellLink_ShortcutDialog [Internal]
+ *
+ * creates a shortcut property dialog
+ */
+
+static HRESULT WINAPI
+ShellLink_ShortcutDialog( IShellLinkImpl *This )
+{
+    PROPSHEETHEADERW pinfo;
+    HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE];
+    HPROPSHEETPAGE hpage;
+    
+    TRACE("ShellLink_ShortcutDialog entered\n");
+
+    memset(hppages, 0x0, sizeof(HPROPSHEETPAGE) * MAX_PROPERTY_SHEET_PAGE);
+
+    hpage = SH_CreatePropertySheetPage("SHELL_FILE_GENERAL_DLG", SH_FileGeneralDlgProc, NULL, (LPARAM)&This->sProduct);
+    if ( hpage == NULL )
+        return E_FAIL;
+
+    hppages[0] = hpage;
+	hpage = SH_CreatePropertySheetPage("SHELL_FILE_SHORTCUT_DLG", SH_ShellLinkDlgProc, NULL, (LPARAM)This);
+	if ( hpage == NULL )
+    {
+        DestroyPropertySheetPage(hppages[0]);
+        return E_FAIL;
+	}
+    hppages[1] = hpage;
+
+    memset(&pinfo, 0x0, sizeof(PROPSHEETHEADERW));
+    pinfo.dwSize = sizeof(PROPSHEETHEADERW);
+    pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE;
+    pinfo.nPages = 2;
+	pinfo.u3.phpage = hppages;
+    pinfo.pszCaption = This->sProduct;
+
+    if ( PropertySheetW(&pinfo) < 0 )
+        return E_FAIL;
+	else
+        return S_OK;
+}
+
 static HRESULT WINAPI
 ShellLink_InvokeCommand( IContextMenu* iface, LPCMINVOKECOMMANDINFO lpici )
 {
@@ -2505,6 +2599,11 @@
     if ( lpici->cbSize < sizeof (CMINVOKECOMMANDINFO) )
         return E_INVALIDARG;
 
+    if ( lpici->lpVerb == MAKEINTRESOURCEA(This->iIdProperties) )
+    {
+      return ShellLink_ShortcutDialog(This);
+    }
+
     if ( lpici->lpVerb != MAKEINTRESOURCEA(This->iIdOpen) )
     {
         ERR("Unknown id %d != %d\n", (INT)lpici->lpVerb, This->iIdOpen );
Index: dlls/shell32/shv_item_cmenu.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shv_item_cmenu.c,v
retrieving revision 1.35
diff -u -r1.35 shv_item_cmenu.c
--- dlls/shell32/shv_item_cmenu.c	2 Sep 2005 11:32:17 -0000	1.35
+++ dlls/shell32/shv_item_cmenu.c	15 Dec 2005 09:41:23 -0000
@@ -384,6 +384,38 @@
 	}
 	return TRUE;
 }
+
+/**************************************************************************
+ * DoProperties
+ *
+ * shows the file property dialog
+ */
+static void DoProperties(
+    IContextMenu2 *iface,
+    HWND hwnd)
+{
+    ItemCmImpl *This = (ItemCmImpl *)iface;
+    char file[MAX_PATH];
+    LPITEMIDLIST	pidlFQ;
+    SHELLEXECUTEINFOA	sei;
+
+    pidlFQ = ILCombine(This->pidl, This->apidl[0]);
+    TRACE("DoProperties _ILIsValue %d _ILIsDesktop %d _ILIsMyComputer %d _ILIsSpecialFolder %d _ILIsDrive %d _ILIsFolder %d _ILIsCPanelStruct %d\n",
+		_ILIsValue(pidlFQ), _ILIsDesktop(pidlFQ),_ILIsMyComputer(pidlFQ),
+        _ILIsDrive(pidlFQ), _ILIsFolder(pidlFQ), _ILIsCPanelStruct(pidlFQ));
+
+    ZeroMemory(&sei, sizeof(sei));
+    sei.cbSize = sizeof(sei);
+    sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME;
+    sei.lpIDList = pidlFQ;
+    sei.hwnd = hwnd;
+    sei.nShow = SW_SHOWNORMAL;
+    sei.lpVerb = "properties";
+    ShellExecuteExA(&sei);
+    SHFree(pidlFQ);
+}
+
+
 /**************************************************************************
 * ISvItemCm_fnInvokeCommand()
 */
@@ -432,6 +464,10 @@
             TRACE("Verb FCIDM_SHVIEW_CUT\n");
             DoCopyOrCut(iface, lpcmi->hwnd, TRUE);
             break;
+        case FCIDM_SHVIEW_PROPERTIES:
+            TRACE("Verb FCIDM_SHVIEW_PROPERTIES\n");
+            DoProperties(iface,lpcmi->hwnd);
+            break;
         default:
             FIXME("Unhandled Verb %xl\n",LOWORD(lpcmi->lpVerb));
         }
--- NUL	?
+++ dlls\shell32\fprop.c	Thu Dec 15 10:41:59 2005
@@ -0,0 +1,662 @@
+/*
+ *                 Shell Library Functions
+ *
+ * Copyright 2005 Johannes Anderwald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include "winerror.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "commdlg.h"
+#include "wine/debug.h"
+
+#include "shellapi.h"
+#include <shlwapi.h>
+#include "shlobj.h"
+#include "shell32_main.h"
+#include "shresdef.h"
+#include "undocshell.h"
+#include <prsht.h>
+
+typedef struct _LANGANDCODEPAGE_ 
+  {
+    WORD lang;
+    WORD code;
+} LANGANDCODEPAGE, *LPLANGANDCODEPAGE;
+
+/*************************************************************************
+ *
+ * SH_CreatePropertySheetPage [Internal]
+ *
+ * creates a property sheet page from an resource name
+ *
+ */
+
+HPROPSHEETPAGE
+SH_CreatePropertySheetPage(LPSTR resname, DLGPROC dlgproc, LPFNPSPCALLBACKW pfnCallback, LPARAM lParam)
+{
+    HRSRC hRes;
+    LPVOID lpsztemplate;
+    PROPSHEETPAGEW ppage;
+
+    if (resname == NULL)
+        return (HPROPSHEETPAGE)0;
+
+    hRes = FindResourceA(shell32_hInstance, resname, (LPSTR)RT_DIALOG);
+
+    if (hRes == NULL)
+        return (HPROPSHEETPAGE)0;
+
+    lpsztemplate = LoadResource(shell32_hInstance, hRes);
+    if (lpsztemplate == NULL)
+        return (HPROPSHEETPAGE)0;
+
+    memset(&ppage, 0x0, sizeof(PROPSHEETPAGE));
+    ppage.dwSize = sizeof(PROPSHEETPAGE);
+    ppage.dwFlags = PSP_DLGINDIRECT;
+    ppage.pResource = lpsztemplate;
+    ppage.pfnDlgProc = dlgproc;
+    ppage.lParam = lParam;
+    if (pfnCallback)
+    {
+        ppage.pfnCallback = pfnCallback;
+        ppage.dwFlags |= PSH_USECALLBACK;
+	}
+    return CreatePropertySheetPageW(&ppage);
+}
+
+/*************************************************************************
+ *
+ * SH_FileGeneralFileType [Internal]
+ *
+ * retrieves file extension description from registry and sets it in dialog
+ *
+ * TODO: retrieve file extension default icon and load it
+ *       find executable name from registry, retrieve description from executable
+ */
+
+BOOL
+SH_FileGeneralSetFileType(HWND hwndDlg, WCHAR * filext)
+{
+     WCHAR name[MAX_PATH];
+     WCHAR value[MAX_PATH];
+     DWORD lname = MAX_PATH;
+     DWORD lvalue = MAX_PATH;
+ 
+     HKEY hKey;
+     LONG result;
+     HWND hDlgCtrl;
+
+
+     if (filext == NULL)
+		 return FALSE;
+
+     hDlgCtrl = GetDlgItem(hwndDlg, 14005);
+
+     if (hDlgCtrl == NULL)
+         return FALSE;
+
+     memset(name, 0x0, sizeof(WCHAR) * MAX_PATH);
+     memset(value, 0x0, sizeof(WCHAR) * MAX_PATH);
+     if (RegOpenKeyW(HKEY_CLASSES_ROOT, filext, &hKey) != ERROR_SUCCESS)
+     {
+         /* the fileextension is unknown, so default to string "FileExtension File" */
+         SendMessageW(hDlgCtrl, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)value);
+         sprintfW(name, value, &filext[1]);
+         SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)name);
+         return TRUE;
+     }
+ 
+     result = RegEnumValueW(hKey, 0, name, &lname, NULL, NULL, (LPBYTE)value, &lvalue);
+     RegCloseKey(hKey);
+
+    if (result != ERROR_SUCCESS)
+        return FALSE;
+ 
+    if (RegOpenKeyW(HKEY_CLASSES_ROOT, value, &hKey) == ERROR_SUCCESS)
+    {
+        lvalue = lname = MAX_PATH;
+        memset(name, 0x0, sizeof(TCHAR) * MAX_PATH);
+        memset(value, 0x0, sizeof(TCHAR) * MAX_PATH);
+        result = RegEnumValueW(hKey,0, name, &lname, NULL, NULL, (LPBYTE)value, &lvalue);
+        RegCloseKey(hKey);
+    }
+
+    /* file extension type */
+    SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)value);
+ 
+    return TRUE;
+}
+/*************************************************************************
+ *
+ * SHFileGeneralGetFileTimeString [Internal]
+ *
+ * formats a given LPFILETIME struct into readable user format 
+ */
+
+BOOL 
+SHFileGeneralGetFileTimeString(LPFILETIME lpFileTime, WCHAR * lpResult)
+{
+    FILETIME ft;
+    SYSTEMTIME dt;
+    WORD wYear;
+    static const WCHAR wFormat[] = {'%','0','2','d','/','%','0','2','d','/','%','0','4','d',' ',' ','%','0','2','d',':','%','0','2','u',0};
+  
+    if (lpFileTime == NULL || lpResult == NULL)
+        return FALSE;
+
+    if (!FileTimeToLocalFileTime(lpFileTime, &ft))
+        return FALSE;
+
+    FileTimeToSystemTime(&ft, &dt);
+
+    wYear = dt.wYear;
+    /* ddmmyy */
+    sprintfW (lpResult, wFormat, dt.wDay, dt.wMonth, wYear, dt.wHour, dt.wMinute);
+    
+    TRACE("result %s\n",debug_strw(lpResult));
+    return TRUE;
+}
+
+/*************************************************************************
+ *
+ * SH_FileGeneralSetText [Internal]
+ *
+ * sets file path string and filename string
+ *
+ */
+
+BOOL 
+SH_FileGeneralSetText(HWND hwndDlg, WCHAR * lpstr)
+{
+    int flength;
+    int plength;
+    WCHAR * lpdir;
+    WCHAR buff[MAX_PATH];
+    HWND hDlgCtrl;
+  
+    if (lpstr == NULL)
+        return FALSE;
+
+    lpdir = strrchrW(lpstr, '\\'); /* find the last occurence of '\\' */
+
+    plength = strlenW(lpstr);
+    flength = strlenW(lpdir);
+  
+    if (lpdir)
+    {
+        /* location text field */
+        strncpyW(buff, lpstr, plength - flength);
+        buff[plength - flength] = UNICODE_NULL;
+        hDlgCtrl = GetDlgItem(hwndDlg, 14009);
+        SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)buff);
+    }
+
+    if(flength > 1)
+    {
+         /* text filename field */
+         strncpyW(buff, &lpdir[1], flength);
+         hDlgCtrl = GetDlgItem(hwndDlg, 14001);
+         SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)buff);
+    }
+
+    return TRUE;
+}
+
+/*************************************************************************
+ *
+ * SH_FileGeneralSetFileSizeTime [Internal]
+ *
+ * retrieves file information from file and sets in dialog
+ *
+ */
+
+BOOL
+SH_FileGeneralSetFileSizeTime(HWND hwndDlg, WCHAR * lpfilename, PULARGE_INTEGER lpfilesize)
+{
+    BOOL result;
+    HANDLE hFile; 
+    FILETIME create_time;
+    FILETIME accessed_time;
+    FILETIME write_time;
+    WCHAR resultstr[MAX_PATH];
+    HWND hDlgCtrl;
+    LARGE_INTEGER file_size;
+
+    if (lpfilename == NULL)
+        return FALSE;
+  
+    hFile = CreateFileW(lpfilename,
+                        GENERIC_READ,
+                        FILE_SHARE_READ,NULL,
+                        OPEN_EXISTING,
+                        FILE_ATTRIBUTE_NORMAL,
+                        NULL);
+
+    if (hFile == INVALID_HANDLE_VALUE)
+    {
+        WARN("failed to open file\n");
+        return FALSE;
+    }
+    
+    result = GetFileTime(hFile, &create_time, &accessed_time, &write_time);
+  
+    if (!result)
+    {
+        WARN("GetFileTime failed\n");
+        return FALSE;
+    }
+    if (SHFileGeneralGetFileTimeString(&create_time,resultstr))
+    {
+        hDlgCtrl = GetDlgItem(hwndDlg, 14015);
+        SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)resultstr);
+    }
+
+    if (SHFileGeneralGetFileTimeString(&accessed_time, resultstr))
+    {
+        hDlgCtrl = GetDlgItem(hwndDlg, 14017);
+        SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)resultstr);
+    }
+
+    if (SHFileGeneralGetFileTimeString(&write_time, resultstr))
+    {
+        hDlgCtrl = GetDlgItem(hwndDlg, 14019);
+        SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)resultstr);
+    }
+  
+    if (!GetFileSizeEx(hFile, &file_size))
+    {
+        WARN("GetFileSize failed\n");
+        CloseHandle(hFile);
+        return FALSE;
+    }
+    CloseHandle(hFile);
+
+    if (!StrFormatByteSizeW(file_size.QuadPart, resultstr, sizeof(resultstr)))
+       return FALSE;
+
+   hDlgCtrl = GetDlgItem(hwndDlg, 14011);
+   TRACE("result %s\n", debug_strw(resultstr));
+   SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)resultstr);
+ 
+   if (lpfilesize)
+       lpfilesize->QuadPart = (ULONGLONG)file_size.QuadPart;
+
+   return TRUE;
+}
+
+/*************************************************************************
+ *
+ * SH_SetFileVersionText [Internal]
+ *
+ *
+ */
+
+BOOL
+SH_FileVersionQuerySetText(HWND hwndDlg, DWORD dlgId, LPVOID pInfo, WCHAR * text, WCHAR ** resptr)
+{
+  UINT reslen;
+  HWND hDlgCtrl;
+
+  if(hwndDlg == NULL || resptr == NULL || text == NULL)
+   return FALSE;
+
+  if(VerQueryValueW(pInfo, text, (LPVOID *)resptr, &reslen))
+  {
+    /* file description property */
+   hDlgCtrl = GetDlgItem(hwndDlg, dlgId);
+   TRACE("%s :: %s\n",debug_strw(text), debug_strw(*resptr));
+   SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)0, (LPARAM)*resptr);
+   return TRUE;
+  }
+  return FALSE;
+}
+
+/*************************************************************************
+ *
+ * SH_FileVersionQuerySetListText [Internal]
+ *
+ * retrieves a version string and adds it to listbox
+ *
+ */
+
+
+BOOL 
+SH_FileVersionQuerySetListText(HWND hwndDlg, LPVOID pInfo, const WCHAR * text, WCHAR **resptr, WORD lang, WORD code)
+{
+  UINT reslen;
+  HWND hDlgCtrl;
+  UINT index;
+  static const WCHAR wFormat[] = { '\\','S','t','r','i','n','g','F','i','l','e','I','n',
+	  'f','o','\\','%','0','4','x','%','0','4','x','\\','%','S',0 };
+  WCHAR buff[256];
+
+  if(hwndDlg == NULL || resptr == NULL || text == NULL)
+   return FALSE;
+
+  sprintfW(buff, wFormat, lang, code, text);
+
+  if(VerQueryValueW(pInfo, buff, (LPVOID *)resptr, &reslen))
+  {
+    /* listbox name property */
+   hDlgCtrl = GetDlgItem(hwndDlg, 14009);
+   TRACE("%s :: %s\n",debug_strw(text), debug_strw(*resptr));
+   index = SendMessageW(hDlgCtrl, LB_ADDSTRING, (WPARAM)-1, (LPARAM)text);
+   SendMessageW(hDlgCtrl, LB_SETITEMDATA, (WPARAM)index, (LPARAM)*resptr);
+   return TRUE;
+  }
+  return FALSE;
+}
+
+/*************************************************************************
+ *
+ * SH_FileVersionInitialize [Internal]
+ *
+ * sets all file version properties in dialog
+ */
+BOOL
+SH_FileVersionInitialize(HWND hwndDlg, WCHAR * lpfilename)
+{
+  LPVOID pBuf;
+  DWORD versize;
+  DWORD handle;
+  LPVOID info = NULL;
+  UINT infolen;
+  WCHAR buff[256];
+  HWND hDlgCtrl;
+  WORD lang;
+  WORD code;
+  LPLANGANDCODEPAGE lplangcode;
+  WCHAR * str;
+  static const WCHAR wVersionFormat[] = { '%','d','.','%','d','.','%','d','.','%','d',0 };
+  static const WCHAR wFileDescriptionFormat[] = { '\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o',
+       '\\','%','0','4','x','%','0','4','x','\\','F','i','l','e','D','e','s','c','r','i','p','t','i','o','n',0 };
+  static const WCHAR wLegalCopyrightFormat[] = { '\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o',
+       '\\','%','0','4','x','%','0','4','x','\\','L','e','g','a','l','C','o','p','y','r','i','g','h','t',0 };  
+  static const WCHAR wTranslation[] = { 'V','a','r','F','i','l','e','I','n','f','o','\\','T','r','a','n','s','l','a','t','i','o','n',0 };
+  static const WCHAR wCompanyName[] = { 'C','o','m','p','a','n','y','N','a','m','e',0 };  
+  static const WCHAR wFileVersion[] = { 'F','i','l','e','V','e','r','s','i','o','n',0 };
+  static const WCHAR wInternalName[] = { 'I','n','t','e','r','n','a','l','N','a','m','e',0 };
+  static const WCHAR wOriginalFilename[] = { 'O','r','i','g','i','n','a','l','F','i','l','e','n','a','m','e',0 };
+  static const WCHAR wProductName[] = { 'P','r','o','d','u','c','t','N','a','m','e',0 };
+  static const WCHAR wProductVersion[] = { 'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0 };
+  static const WCHAR wSlash[] = { '\\',0 };
+
+
+  if(lpfilename == 0)
+    return FALSE;
+
+  if(!(versize = GetFileVersionInfoSizeW(lpfilename, &handle)))
+  {
+	WARN("GetFileVersionInfoSize failed\n");
+    return FALSE;
+  }
+  
+  if(!(pBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, versize)))
+  {
+	WARN("HeapAlloc failed bytes %x\n",versize);
+    return FALSE;
+  }
+  
+  if(!GetFileVersionInfoW(lpfilename, handle, versize, pBuf))
+  {
+	HeapFree(GetProcessHeap(), 0, pBuf);
+    return FALSE;
+  }
+  if(VerQueryValueW(pBuf, wSlash, &info, &infolen))
+  {
+    VS_FIXEDFILEINFO * inf = (VS_FIXEDFILEINFO *)info;
+	sprintfW(buff, wVersionFormat,inf->dwFileVersionMS & 0xFFFF0000,
+		                                  inf->dwFileVersionMS & 0x0000FFFF,
+										  inf->dwFileVersionLS & 0xFFFF0000,
+										  inf->dwFileVersionLS & 0x0000FFFF);
+
+   hDlgCtrl = GetDlgItem(hwndDlg, 14001);
+   TRACE("MS %x LS %x res %s \n",inf->dwFileVersionMS, inf->dwFileVersionLS, debug_strw(buff));
+   SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)buff);
+  }
+  if(VerQueryValueW(pBuf, wTranslation, (LPVOID *)&lplangcode, &infolen))
+  {
+    /* FIXME find language from current locale / if not available,
+	 * default to english
+	 * for now default to first available language
+     */
+    lang = lplangcode->lang;
+    code = lplangcode->code;
+  }
+  
+  sprintfW(buff, wFileDescriptionFormat, lang, code);
+  SH_FileVersionQuerySetText(hwndDlg, 14003, pBuf, buff, &str);
+    
+  sprintfW(buff, wLegalCopyrightFormat, lang, code);
+  SH_FileVersionQuerySetText(hwndDlg, 14005, pBuf, buff, &str);
+
+  /* listbox properties */
+  SH_FileVersionQuerySetListText(hwndDlg, pBuf, wCompanyName, &str, lang, code);
+  SH_FileVersionQuerySetListText(hwndDlg, pBuf, wFileVersion, &str, lang, code);
+  SH_FileVersionQuerySetListText(hwndDlg, pBuf, wInternalName, &str, lang, code);
+
+  /* FIXME insert language identifier */
+
+  SH_FileVersionQuerySetListText(hwndDlg, pBuf, wOriginalFilename, &str, lang, code);
+  SH_FileVersionQuerySetListText(hwndDlg, pBuf, wProductName, &str, lang, code);
+  SH_FileVersionQuerySetListText(hwndDlg, pBuf, wProductVersion, &str, lang, code);
+  SetWindowLong(hwndDlg, DWL_USER, (LONG)pBuf);
+  return TRUE;
+}
+
+/*************************************************************************
+ *
+ * SH_FileVersionDlgProc
+ *
+ * wnd proc of 'Version' property sheet page
+ */
+INT_PTR 
+CALLBACK 
+SH_FileVersionDlgProc(   
+    HWND hwndDlg,
+    UINT uMsg,
+    WPARAM wParam,
+    LPARAM lParam
+)
+{
+  LPPROPSHEETPAGE ppsp;
+  WCHAR * lpstr;
+  LPVOID * buf;
+  switch(uMsg)
+  {
+  case WM_INITDIALOG:
+	 ppsp = (LPPROPSHEETPAGE)lParam;
+	 if(ppsp == NULL)
+	   break;
+
+	 TRACE("WM_INITDIALOG hwnd %p lParam %p ppsplParam %x\n",hwndDlg, lParam, ppsp->lParam);
+
+	 lpstr = (WCHAR *)ppsp->lParam;
+
+	 if(lpstr == NULL)
+	   break;
+
+	 return SH_FileVersionInitialize(hwndDlg, lpstr);
+
+
+  case WM_COMMAND:
+     if(LOWORD(wParam) == 14009 && HIWORD(wParam) == LBN_DBLCLK)
+	 {
+       HWND hDlgCtrl;
+	   LRESULT lresult;
+	   WCHAR * str;
+	   
+	   hDlgCtrl = GetDlgItem(hwndDlg, 14009);
+	   lresult = SendMessageW(hDlgCtrl, LB_GETCURSEL, (WPARAM)NULL, (LPARAM)NULL);
+       if(lresult == LB_ERR)
+	   {
+	     break;
+	   }
+       str = (WCHAR *)SendMessageW(hDlgCtrl, LB_GETITEMDATA, (WPARAM)lresult, (LPARAM)NULL);
+
+	   if(str == NULL)
+	   {
+		 break;
+	   }
+	   hDlgCtrl = GetDlgItem(hwndDlg, 14010);
+       TRACE("hDlgCtrl %x string %s \n",hDlgCtrl, debug_strw(str));
+	   SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)str);
+       return TRUE;
+	 }
+  case WM_DESTROY:
+       buf = (LPVOID)GetWindowLong(hwndDlg, DWL_USER);
+	   HeapFree(GetProcessHeap(), 0, buf);
+  default:
+	  break;
+  }
+  return FALSE;
+}
+
+/*************************************************************************
+ *
+ * SH_FileGeneralDlgProc
+ *
+ * wnd proc of 'General' property sheet page
+ *
+ */
+
+INT_PTR 
+CALLBACK 
+SH_FileGeneralDlgProc(   
+    HWND hwndDlg,
+    UINT uMsg,
+    WPARAM wParam,
+    LPARAM lParam
+)
+{
+    LPPROPSHEETPAGEW ppsp;
+    WCHAR * lpstr;
+    switch(uMsg)
+    {
+    case WM_INITDIALOG:
+        ppsp = (LPPROPSHEETPAGEW)lParam;
+        if (ppsp == NULL)
+            break;
+        TRACE("WM_INITDIALOG hwnd %p lParam %p ppsplParam %x\n",hwndDlg, lParam, ppsp->lParam);
+
+        lpstr = (WCHAR *)ppsp->lParam;
+
+        if ( lpstr == NULL)
+		{
+            ERR("no filename\n");
+            break;
+        }
+        /* set general text properties filename filelocation and icon */
+        SH_FileGeneralSetText(hwndDlg, lpstr);
+        /* enumerate file extension from registry and application which opens it*/
+        SH_FileGeneralSetFileType(hwndDlg, strrchrW(lpstr, '.'));
+        /* set file time create/modfied/accessed */
+        SH_FileGeneralSetFileSizeTime(hwndDlg, lpstr, NULL);
+        return TRUE;
+  default:
+      break;
+  }
+  return FALSE;
+}
+
+
+/*************************************************************************
+ *
+ * SH_ShowPropertiesDialog
+ *
+ * called from ShellExecuteExW32
+ * 
+ * lpf contains (quoted) path of folder/file
+ *
+ * TODO: provide button change application type if file has registered type
+ *        make filename field editable and apply changes to filename on close
+ */
+	
+BOOL
+SH_ShowPropertiesDialog(WCHAR * lpf)
+{
+    PROPSHEETHEADERW pinfo;
+    HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE];
+    HPROPSHEETPAGE hpage;
+    WCHAR wFileName[MAX_PATH];
+	UINT num_pages = 0;
+	DWORD dwHandle = 0;
+  
+    TRACE("SH_ShowPropertiesDialog entered\n");
+
+    if (lpf== NULL)
+        return FALSE;
+  
+    if ( !strlenW(lpf) )
+        return FALSE;
+
+    memset(hppages, 0x0, sizeof(HPROPSHEETPAGE) * MAX_PROPERTY_SHEET_PAGE);
+    if (lpf[0] == '"')
+    {
+        /* remove quotes from lpf */
+        LPWSTR src = lpf + 1;
+        LPWSTR dst = wFileName;
+      
+        while(*src && *src!='"')
+            *dst++ = *src++;
+
+        *dst = '\0';
+    }
+	else
+	{
+	    strcpyW(wFileName, lpf);
+	}
+
+    if (PathIsDirectoryW(wFileName) || strlenW(wFileName) == 3)
+    {
+        FIXME("directory / drive resources are missing\n");
+        return FALSE;
+    }
+    hpage = SH_CreatePropertySheetPage("SHELL_FILE_GENERAL_DLG", SH_FileGeneralDlgProc, NULL, (LPARAM)wFileName);
+
+    if (hpage == NULL)
+        return FALSE;
+
+    hppages[num_pages] = hpage;
+    num_pages++;
+    if ( GetFileVersionInfoSizeW(ptr, &dwHandle) )
+	{
+         if ( (hpage = SH_CreatePropertySheetPage("SHELL_FILE_VERSION_DLG",SH_FileVersionDlgProc, NULL, (LPARAM)ptr))!= NULL)
+         {
+              hppages[num_pages] = hpage;
+		      num_pages++;
+         }
+	}
+    memset(&pinfo, 0x0, sizeof(PROPSHEETHEADERW));
+    pinfo.dwSize = sizeof(PROPSHEETHEADERW);
+    pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE;
+    pinfo.nPages = num_pages;
+    pinfo.phpage = hppages;
+    pinfo.pszCaption = wFileName;
+    return (PropertySheetW(&pinfo) != -1);
+}
+/*EOF */


More information about the wine-patches mailing list