Vinicius Gonçalves
Vinicius Gonçalves

Reputation: 2724

Detect OpenFileDialog

For a very peculiar requirement of a DLP software, I'm trying to detect OpenFileDialogs and cancel the file selection action, after capturing the selected file.

How am I trying to do this?

I put a global hook on the mouse and keyboard. I detect all actions that the user can perform to select a file in the OpenFileDialog window.

What I could not do until now is to detect if the window is an OpenFileDialog by hwnd.

Why am I trying this way?

I am a high level programmer and tried initially with windows hooks, without success. I tried with easyhook and deviare2. There seems to be no simpler way to put a global hook in a COM (IFileDialog) component call.

Is there any way to detect if a window is the default Windows OpenFileDialog window by hwnd?

public bool IsOpenFileDialog(IntPtr hwnd)
{
    return ?
}

Upvotes: 1

Views: 1735

Answers (1)

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186668

As a partial solution (an adversary can mimic such a dialog), I suggest checking if the window a standard dialog and if it is, does it have "Save" in the caption (you can well put a better ctriterium here):

First, let's check class:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms633574(v=vs.85).aspx

 using System.Runtime.InteropServices;

 ... 

 [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
  private static extern int GetClassName(IntPtr hWnd, 
    StringBuilder lpClassName, 
    int nMaxCount);

  private static String WndClassName(IntPtr handle) {
    int length = 1024;

    StringBuilder sb = new StringBuilder(length);

    GetClassName(handle, sb, length);

    return sb.ToString();
  }

  public static bool IsDialogClassName(IntPtr handle) {
    // Standard windows dialogs like OpenFileDialog, SaveFileDialog have #32770 class name 
    return "#32770".Equals(WndClassName(handle));
  } 

However, it's too wide criterium: both Save File Dialog and Open File Dialog pass it. Let's check window's caption:

  [DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
   private static extern int GetWindowTextLength(IntPtr hWnd);

  [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
   static extern int GetWindowText(IntPtr hWnd, 
     StringBuilder text, 
     int length);

   private static String WindowText(IntPtr handle) {
     int length = GetWindowTextLength(handle);

     StringBuilder sb = new StringBuilder(length + 1);

     GetWindowText(handle, sb, length + 1);

     return sb.ToString();
   }

   public static bool IsSaveCaption(IntPtr handle) {
     //TODO: put a better check for dialog's caption here
     return WindowText(handle).IndexOf("Save", StringComparison.OrdinalIgnoreCase) >= 0;
   } 

Finally:

  public bool IsOpenFileDialog(IntPtr hwnd) {
    return IsDialogClassName(hwnd) && 
           !IsSaveCaption(hwnd);
  }

Sure you may want some other criteria, but I hope these two will be enough

Upvotes: 5

Related Questions