Page 1 of 1

[Solved] #WM_CLOSE fails on admin windows

Posted: Sat Dec 14, 2013 4:44 pm
by PB
For years I've been using "PostMessage_(hWnd,#WM_CLOSE,0,0)" to
close a third-party window, and it's always worked because I used to
be logged in as an admin all the time.

These days I always run as a limited account, and I noticed that if I run
Notepad as an admin (right-click it and select "Run as administrator"),
that my PostMessage above doesn't actually close it anymore! :shock:

So what can I do to close the Notepad window in future? Thanks!

Re: #WM_CLOSE fails on admin windows

Posted: Sat Dec 14, 2013 5:14 pm
by freak
I don't think there is a way. If there was a way around it then the whole concept of privilege isolation would be useless.

If your target program runs as administrator then your sender program must do so as well.

Re: #WM_CLOSE fails on admin windows

Posted: Sat Dec 14, 2013 5:19 pm
by Shield
There is no solution (thanks thor!)*. If you check GetLastError(), it will return the "access denied" error code.
The only way your program can do that is if it is being run with elevated privileges as well.

Alternatively, ChangeWindowMessageFilterEx() can be used to change this behavior for a specific window.
Of course this function is probably of limited use for you as it requires admin rights as well if applied on external windows.

*edit: Apparently there is a safe one, see below.

Re: #WM_CLOSE fails on admin windows

Posted: Sat Dec 14, 2013 5:40 pm
by IdeasVacuum
Isn't your app starting-up Notepad with RunProgram()? If not, then do that and you have control of what happens next.

Re: #WM_CLOSE fails on admin windows

Posted: Sun Dec 15, 2013 2:13 am
by PB
> Isn't your app starting-up Notepad with RunProgram()?

No, see my first post. :)

The reason I ask how it's done, is because there's another app
which can do it, even if Notepad was launched as admin, and
even when I run that other app as limited.

Re: #WM_CLOSE fails on admin windows

Posted: Sun Dec 15, 2013 3:15 am
by IdeasVacuum
...I think it needs to be a trusted app from a known publisher. If that criteria is true, Windows will allow a temporary promotion of the User to Admin. Not sure if that remains true for Win8.1 however.

You do not explain why you want to close the other application. If I were using your app, why would I want it to close another app I have running? Does it do that without asking me first?

Re: #WM_CLOSE fails on admin windows

Posted: Sun Dec 15, 2013 4:07 am
by JHPJHP
Removed; post ignored.

Re: #WM_CLOSE fails on admin windows

Posted: Sun Dec 15, 2013 4:46 am
by Shield
I found a solution: By using WM_SYSCOMMAND you can safely send the close message
to an administrator window. WM_SYSCOMMAND will be used when default window actions
are being issued, such as closing and minimizing (via context menu) and are therefore not blocked.

Code: Select all

hwnd = FindWindow_(0, "Untitled - Notepad")
PostMessage_(hwnd, #WM_SYSCOMMAND, #SC_CLOSE, 0)

Re: #WM_CLOSE fails on admin windows

Posted: Sun Dec 15, 2013 5:12 am
by skywalk
Shield, I can't remember when or why, but I had to do the same thing for my window closer tool :?:

Code: Select all

Structure winINFO
  hW.i      ; handle
  left.i
  top.i
  right.i
  bottom.i
  Wd.i
  Ht.i
  wT$       ; window title
EndStructure
Global NewList wil.winINFO()  ; Window Info list

Macro PB_CP
  ProgramFilename() + "::" + #PB_Compiler_Procedure
EndMacro
Macro MRI(txt)  ; MessageBox i Info = #MB_ICONASTERISK | #MB_ICONINFORMATION
  MessageRequester(PB_CP, txt, #MB_ICONINFORMATION)
EndMacro
Macro MRE(txt)  ; MessageBox x Error = #MB_ICONHAND | #MB_ICONSTOP | #MB_ICONERROR
  MessageRequester(PB_CP, txt, #MB_ICONERROR)
EndMacro

Procedure RestoreX(DataLabel.i)
  CompilerSelect #PB_Compiler_Processor
  CompilerCase #PB_Processor_x86
    !MOV eax, [p.v_DataLabel]   ; instead of -> !MOV eax, [esp+8]
    !MOV [PB_DataPointer], eax
  CompilerCase #PB_Processor_x64
    !MOV rax, [p.v_DataLabel]   ; instead of -> !MOV rax, [rsp+64]
    !MOV [PB_DataPointer], rax
  CompilerDefault
    MRE("Error: Unknown Processor.")
  CompilerEndSelect
EndProcedure

Procedure.i win_GetInfo_CB(hW.i, lp.i)
  Protected.s wt$ = Space(#MAX_PATH)
  Protected wp.WINDOWPLACEMENT
  If hW
    AddElement(wil())
    wil()\hW = hW
    If IsWindowVisible_(hW)
      GetWindowText_(hW, @wt$, #MAX_PATH)
      If wt$
        wil()\wT$ = wt$
        Debug wt$
        GetWindowPlacement_(hW, @wp)
        wil()\left = wp\rcNormalPosition\left
        wil()\top = wp\rcNormalPosition\top
        wil()\right = wp\rcNormalPosition\right
        wil()\bottom = wp\rcNormalPosition\bottom
        wil()\Wd = wil()\right - wil()\left
        wil()\Ht = wil()\bottom - wil()\top
      EndIf
    EndIf
    ProcedureReturn 1   ; Continue search
  Else
    ProcedureReturn 0   ; Done
  EndIf
EndProcedure

Procedure.i CT_CloseExtraPBWin(DataLabel.i)
  ; Create list of existing windows + handles.
  ; Then cycle through and close them.
  ; Attempts to close via callback fails for some windows.
  ; CRITICAL: Delay() cmd after SendMessage_() for settling time.
  Protected.i ri
  Protected.s winToClose$
  ClearList(wil())
  EnumWindows_(@win_GetInfo_CB(), 0)
  ; Cycle through retrieved window list and close PB window types.
  ResetList(wil())
  ForEach wil()
    RestoreX(DataLabel)
    Repeat      ; Enumerate all PB Window types
      Read.s winToClose$
      If FindString(wil()\wT$, winToClose$)
        ;ri = SendMessage_(wil()\hW, #WM_CLOSE, 0, 0) ; This fails in some cases
        ri = SendMessage_(wil()\hW, #WM_SYSCOMMAND, #SC_CLOSE, 0)
        Delay(50)
        If ri = #S_OK
          ri = 1
        Else
          MRE("Error: Unable to close " + wil()\wT$)
          ri = -1
        EndIf
        Break
      EndIf
    Until winToClose$ = "Q"
  Next
  ClearList(wil())
  ProcedureReturn ri
EndProcedure

DataSection
  PBWindowNames:
  Data.s "Asm Debugger", "Data Breakpoints", "Debug Output", "Library Viewer", "Memory Viewer"
  Data.s "Procedure Callstack", "Profiler Settings", "Profiler", "Purifier Settings", "Structure Viewer"
  Data.s "Variable Viewer", "Watch List", "HTML Help", "Find in files", "Platform SDK Collection"
  Data.s "Q"  ; Quit
EndDataSection

mri(Str(CT_CloseExtraPBWin(?PBWindowNames)))

Re: #WM_CLOSE fails on admin windows

Posted: Sun Dec 15, 2013 8:04 am
by PB

Code: Select all

PostMessage_(hWnd, #WM_SYSCOMMAND, #SC_CLOSE, 0)
Ah, that does the trick! Thanks, Shield! :)