msi 3: Verify the path in the PathEdit control [try3]

James Hawkins truiken at gmail.com
Thu Aug 31 15:42:57 CDT 2006


Hi,

This version doesn't remove control checks added by Mike.

Changelog:
* Verify the path in the PathEdit control.

 dlls/msi/dialog.c |  107 +++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 86 insertions(+), 21 deletions(-)

-- 
James Hawkins
-------------- next part --------------
diff --git a/dlls/msi/dialog.c b/dlls/msi/dialog.c
index ab58219..824db78 100644
--- a/dlls/msi/dialog.c
+++ b/dlls/msi/dialog.c
@@ -1388,6 +1388,13 @@ static UINT msi_dialog_progress_bar( msi
 
 /******************** Path Edit ********************************************/
 
+struct msi_pathedit_info
+{
+    msi_dialog *dialog;
+    msi_control *control;
+    WNDPROC oldproc;
+};
+
 static LPWSTR msi_get_window_text( HWND hwnd )
 {
     UINT sz, r;
@@ -1407,21 +1414,63 @@ static LPWSTR msi_get_window_text( HWND 
     return buf;
 }
 
-static UINT msi_dialog_pathedit_handler( msi_dialog *dialog,
-                msi_control *control, WPARAM param )
+static void msi_dialog_update_pathedit( msi_dialog *dialog, msi_control *control )
 {
-    LPWSTR buf, prop;
+    LPWSTR prop, path;
     BOOL indirect;
 
-    if( HIWORD(param) != EN_KILLFOCUS )
-        return ERROR_SUCCESS;
+    if (!control && !(control = msi_dialog_find_control_by_type( dialog, szPathEdit )))
+       return;
+
+    indirect = control->attributes & msidbControlAttributesIndirect;
+    prop = msi_dialog_dup_property( dialog, control->property, indirect );
+
+    path = msi_dup_property( dialog->package, prop );
+    SetWindowTextW( control->hwnd, path );
+    SendMessageW( control->hwnd, EM_SETSEL, 0, -1 );
+
+    msi_free( path );
+    msi_free( prop );
+}
+
+/* FIXME: test when this should fail */
+static BOOL msi_dialog_verify_path( LPWSTR path )
+{
+    if ( !lstrlenW( path ) )
+        return FALSE;
+
+    if ( PathIsRelativeW( path ) )
+        return FALSE;
+
+    return TRUE;
+}
+
+/* returns TRUE if the path is valid, FALSE otherwise */
+static BOOL msi_dialog_onkillfocus( msi_dialog *dialog, msi_control *control )
+{
+    LPWSTR buf, prop;
+    BOOL indirect;
+    BOOL valid;
 
     indirect = control->attributes & msidbControlAttributesIndirect;
     prop = msi_dialog_dup_property( dialog, control->property, indirect );
 
-    /* FIXME: verify the new path */
     buf = msi_get_window_text( control->hwnd );
-    MSI_SetPropertyW( dialog->package, prop, buf );
+
+    if ( !msi_dialog_verify_path( buf ) )
+    {
+        /* FIXME: display an error message box */
+        ERR("Invalid path %s\n", debugstr_w( buf ));
+        valid = FALSE;
+        SetFocus( control->hwnd );
+    }
+    else
+    {
+        valid = TRUE;
+        MSI_SetPropertyW( dialog->package, prop, buf );
+    }
+
+    msi_dialog_update_pathedit( dialog, control );
 
     TRACE("edit %s contents changed, set %s\n", debugstr_w(control->name),
           debugstr_w(prop));
@@ -1429,40 +1478,56 @@ static UINT msi_dialog_pathedit_handler(
     msi_free( buf );
     msi_free( prop );
 
-    return ERROR_SUCCESS;
+    return valid;
 }
 
-static void msi_dialog_update_pathedit( msi_dialog *dialog, msi_control *control )
+static LRESULT WINAPI MSIPathEdit_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
-    LPWSTR prop, path;
-    BOOL indirect;
+    struct msi_pathedit_info *info = GetPropW(hWnd, szButtonData);
+    LRESULT r = 0;
 
-    if (!control && !(control = msi_dialog_find_control_by_type( dialog, szPathEdit ) ))
-        return;
+    TRACE("%p %04x %08x %08lx\n", hWnd, msg, wParam, lParam);
 
-    indirect = control->attributes & msidbControlAttributesIndirect;
-    prop = msi_dialog_dup_property( dialog, control->property, indirect );
+    if ( msg == WM_KILLFOCUS )
+    {
+        /* if the path is invalid, don't handle this message */
+        if ( !msi_dialog_onkillfocus( info->dialog, info->control ) )
+            return 0;
+    }
 
-    path = msi_dup_property( dialog->package, prop );
-    SetWindowTextW( control->hwnd, path );
-    SendMessageW( control->hwnd, EM_SETSEL, 0, -1 );
+    r = CallWindowProcW(info->oldproc, hWnd, msg, wParam, lParam);
 
-    msi_free( path );
-    msi_free( prop );
+    if ( msg == WM_NCDESTROY )
+    {
+        msi_free( info );
+        RemovePropW( hWnd, szButtonData );
+    }
+
+    return r;
 }
 
 static UINT msi_dialog_pathedit_control( msi_dialog *dialog, MSIRECORD *rec )
 {
+    struct msi_pathedit_info *info;
     msi_control *control;
     LPCWSTR prop;
 
+    info = msi_alloc( sizeof *info );
+    if (!info)
+        return ERROR_FUNCTION_FAILED;
+
     control = msi_dialog_add_control( dialog, rec, szEdit,
                                       WS_BORDER | WS_TABSTOP );
-    control->handler = msi_dialog_pathedit_handler;
     control->attributes = MSI_RecordGetInteger( rec, 8 );
     prop = MSI_RecordGetString( rec, 9 );
     control->property = msi_dialog_dup_property( dialog, prop, FALSE );
 
+    info->dialog = dialog;
+    info->control = control;
+    info->oldproc = (WNDPROC) SetWindowLongPtrW( control->hwnd, GWLP_WNDPROC,
+                                                 (LONG_PTR)MSIPathEdit_WndProc );
+    SetPropW( control->hwnd, szButtonData, info );
+
     msi_dialog_update_pathedit( dialog, control );
 
     return ERROR_SUCCESS;
-- 
1.4.2


More information about the wine-patches mailing list