Author Topic: OFN OFNOTIFY and Associated Constants  (Read 3097 times)

dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
OFN OFNOTIFY and Associated Constants
« on: August 31, 2013, 12:26:17 AM »
windows.inc does not have the OFNOTIFY structure defined:
Code: [Select]
typedef struct _OFNOTIFY {
  NMHDR          hdr;
  LPOPENFILENAME lpOFN;
  LPTSTR         pszFile;
} OFNOTIFY, *LPOFNOTIFY;

also, the associated notification code constants are incorrectly defined as:
Code: [Select]
CDN_INITDONE                     equ 0000h
CDN_SELCHANGE                    equ 0001h
CDN_FOLDERCHANGE                 equ 0002h
CDN_SHAREVIOLATION               equ 0003h
CDN_HELP                         equ 0004h
CDN_FILEOK                       equ 0005h
CDN_TYPECHANGE                   equ 0006h
CDN_INCLUDEITEM                  equ 0007h
should be:
Code: [Select]
CDN_INITDONE                     equ CDN_FIRST-0000h
CDN_SELCHANGE                    equ CDN_FIRST-0001h
CDN_FOLDERCHANGE                 equ CDN_FIRST-0002h
CDN_SHAREVIOLATION               equ CDN_FIRST-0003h
CDN_HELP                         equ CDN_FIRST-0004h
CDN_FILEOK                       equ CDN_FIRST-0005h
CDN_TYPECHANGE                   equ CDN_FIRST-0006h
CDN_INCLUDEITEM                  equ CDN_FIRST-0007h

EDIT: CDN_FIRST is correctly defined as 0-601 (decimal, not hex)
« Last Edit: August 31, 2013, 05:16:29 AM by dedndave »

MichaelW

  • Global Moderator
  • Member
  • *****
  • Posts: 1209
Re: OFN OFNOTIFY and Associated Constants
« Reply #1 on: August 31, 2013, 07:08:10 AM »
And as a check against the Microsoft header files:
Code: [Select]
#include <windows.h>
#include <stdio.h>
#include <conio.h>
void main( void )
{
    printf("CDN_FIRST           %d\n",CDN_FIRST);
    printf("CDN_LAST            %d\n\n",CDN_LAST);
    printf("sizeof(OFNOTIFY)    %d\n\n", sizeof(OFNOTIFY));
    printf("CDN_INITDONE        %d\n",CDN_INITDONE);
    printf("CDN_SELCHANGE       %d\n",CDN_SELCHANGE);
    printf("CDN_FOLDERCHANGE    %d\n",CDN_FOLDERCHANGE);
    printf("CDN_SHAREVIOLATION  %d\n",CDN_SHAREVIOLATION);
    printf("CDN_HELP            %d\n",CDN_HELP);
    printf("CDN_FILEOK          %d\n",CDN_FILEOK);
    printf("CDN_TYPECHANGE      %d\n",CDN_TYPECHANGE);
    printf("CDN_INCLUDEITEM     %d\n\n",CDN_INCLUDEITEM);
    getch();
}
Code: [Select]
CDN_FIRST           -601
CDN_LAST            -699

sizeof(OFNOTIFY)    20

CDN_INITDONE        -601
CDN_SELCHANGE       -602
CDN_FOLDERCHANGE    -603
CDN_SHAREVIOLATION  -604
CDN_HELP            -605
CDN_FILEOK          -606
CDN_TYPECHANGE      -607
CDN_INCLUDEITEM     -608
Well Microsoft, here’s another nice mess you’ve gotten us into.

MichaelW

  • Global Moderator
  • Member
  • *****
  • Posts: 1209
Re: OFN OFNOTIFY and Associated Constants
« Reply #2 on: September 02, 2013, 01:53:17 PM »
This is my attempt at a definition that will work with windows.inc, along with a simple test app.
Code: [Select]
;==============================================================================
include \masm32\include\masm32rt.inc
;==============================================================================

LPOPENFILENAMEW TYPEDEF PTR OPENFILENAMEW
LPOPENFILENAMEA TYPEDEF PTR OPENFILENAMEA

IFDEF __UNICODE__
    LPOPENFILENAME equ <LPOPENFILENAMEW>
ELSE
    LPOPENFILENAME equ <LPOPENFILENAMEA>
ENDIF

;typedef struct _OFNOTIFY {
;  NMHDR          hdr;
;  LPOPENFILENAME lpOFN;
;  LPTSTR         pszFile;
;} OFNOTIFY, *LPOFNOTIFY;

OFNOTIFY STRUCT
    hdr     NMHDR           <>
    lpOFN   LPOPENFILENAME  ?
    pszFile LPTSTR          ?
OFNOTIFY ENDS

;==============================================================================
.data
    ofno OFNOTIFY <>
    ofn OPENFILENAME <>
    strFile db 100 dup(0)
.code
;==============================================================================

OFNHookProc proc hdlg:HWND, uiMsg:UINT, wParam:WPARAM, lParam:LPARAM
    SWITCH uiMsg
        CASE WM_NOTIFY
            mov eax, lParam
            mov eax, [eax].OFNOTIFY.lpOFN
            printf("%Xh\n\n",eax)
    ENDSW
    ret
OFNHookProc endp

;==============================================================================
start:
;==============================================================================
    printf("%d\n",SIZEOF OFNOTIFY)
    printf("%Xh\n\n",ADDR ofn)

    mov ofn.lStructSize, SIZEOF OPENFILENAME
    mov ofn.lpstrFilter, chr$("All Files (*.*)",0,"*.*",0,0)
    mov ofn.lpstrFile, OFFSET strFile
    mov ofn.nMaxFile, SIZEOF strFile
    mov ofn.Flags, OFN_EXPLORER or OFN_ENABLEHOOK or OFN_FILEMUSTEXIST
    mov ofn.lpfnHook, OFNHookProc

    invoke GetOpenFileName, ADDR ofn

    inkey
    exit
;==============================================================================
end start
Code: [Select]
20
403014h

403014h

403014h

403014h
Well Microsoft, here’s another nice mess you’ve gotten us into.

dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
Re: OFN OFNOTIFY and Associated Constants
« Reply #3 on: September 02, 2013, 06:32:45 PM »
nice Michael

i wanted my app to accept filenames with no extension
then - append the extension, according to the drop-down box selection and test to see if the file exists
in this case, i only had 2 different file types for SaveAs
but, something like Paint may have several

my final OfnHookProc looks like this
Code: [Select]
;***********************************************************************************************

OfnHookProc PROC hwndDlg:HWND,uiMsg:UINT,wParam:WPARAM,lParam:LPARAM

_CDN_INITDONE       EQU -601
_CDN_SELCHANGE      EQU -602
_CDN_FOLDERCHANGE   EQU -603
_CDN_SHAREVIOLATION EQU -604
_CDN_HELP           EQU -605
_CDN_FILEOK         EQU -606
_CDN_TYPECHANGE     EQU -607
_CDN_INCLUDEITEM    EQU -608

    .if uiMsg==WM_NOTIFY
        mov     edx,lParam
        .if [edx].OFNOTIFY.hdr.code==_CDN_FILEOK
            push    ebx
            push    esi
            push    edi
            push    hwndDlg
            push    ebp
            mov     ebx,[edx].OFNOTIFY.lpOFN                             ;EBX = lpOFN
            mov     ebp,esp
            mov     esi,[ebx].OPENFILENAME.lpstrFile
            INVOKE  GetStrLen,esi
            lea     ecx,[eax+1]
            add     eax,sizeof szExists+7
            mov     edi,esp
            and     al,-4
            sub     edi,eax

            ASSUME  FS:Nothing

            .repeat
                push    edx
                mov     esp,fs:[8]
            .until edi>=esp

            ASSUME  FS:ERROR

            mov     esp,edi
            rep     movsb
            movzx   edx,word ptr [ebx].OPENFILENAME.nFileExtension
            INVOKE  SetSaveAsExt,edx,[ebx].OPENFILENAME.nFilterIndex,esp
            xor     eax,eax
            mov     ebx,esp
            push    ecx
            push    eax
            push    eax
            sub     esp,sizeof WIN32_FILE_ATTRIBUTE_DATA-8
            INVOKE  GetFileAttributesEx,ebx,eax,esp
            add     esp,sizeof WIN32_FILE_ATTRIBUTE_DATA-8
            pop     edx
            pop     eax
            or      eax,edx
            pop     ecx
            .if !ZERO?
                lea     edi,[ebx+ecx]
                mov     esi,offset szExists
                mov     ecx,sizeof szExists
                rep     movsb
                INVOKE  MessageBox,[ebp+4],ebx,offset szSaveAs,MB_YESNO or MB_ICONEXCLAMATION
                .if eax==IDNO
                    INVOKE  SetWindowLong,[ebp+4],DWL_MSGRESULT,TRUE
                    mov     eax,TRUE
                .else
                    xor     eax,eax
                .endif
            .endif
            leave
            pop     edx
            pop     edi
            pop     esi
            pop     ebx
        .else
            xor     eax,eax
        .endif
    .else
        xor     eax,eax
    .endif
    ret

OfnHookProc ENDP

;***********************************************************************************************

notice that, if the file exists but has 0 size, i treat it as "ok to overwrite"

i use a support routine that sets the "test" extension, according to the nFilterIndex value
then, in the SaveAs dialog proc, i use the same SetSaveAsExt function to set the final extension

i also used an "extended" version of the OPENFILENAME structure
Code: [Select]
;EX_OPENFILENAME  STRUCT
; lStructSize       DWORD         ?
; hwndOwner         HWND          ?
; hInstance         HINSTANCE     ?
; lpstrFilter       LPCTSTR       ?
; lpstrCustomFilter LPTSTR        ?
; nMaxCustFilter    DWORD         ?
; nFilterIndex      DWORD         ?
; lpstrFile         LPTSTR        ?
; nMaxFile          DWORD         ?
; lpstrFileTitle    LPTSTR        ?
; nMaxFileTitle     DWORD         ?
; lpstrInitialDir   LPCTSTR       ?
; lpstrTitle        LPCTSTR       ?
; Flags             DWORD         ?
; nFileOffset       WORD          ?
; nFileExtension    WORD          ?
; lpstrDefExt       LPCTSTR       ?
; lCustData         LPARAM        ?
; lpfnHook          LPOFNHOOKPROC ?
; lpTemplateName    LPCTSTR       ?
; pvReserved        LPVOID        ?
; dwReserved        DWORD         ?
; FlagsEx           DWORD         ?
the last 3 members are not present in the OPENFILENAME structure defined in windows.inc
if you hook a new style dialog, and want it to have the places bar, you will need to use the longer structure

because i had to "discover" the windows.inc discrepancies as i went along,
it took me 2 days of farting around to get what i wanted   :lol:

ToutEnMasm

  • Member
  • *****
  • Posts: 1189
    • EditMasm
Re: OFN OFNOTIFY and Associated Constants
« Reply #4 on: October 30, 2013, 07:14:27 PM »

There is no need to search anything

All this is perfectly defined in the commdlg.sdk and perhaps in some others translated file

Extract from commdlg.sdk
Quote
OFNOTIFYA   STRUCT   DEFALIGNMASM
   hdr NMHDR <>
   lpOFN DWORD ?
   pszFile DWORD ? ; May be NULL
OFNOTIFYA      ENDS

CDN_FIRST   equ   < 0 - 601>
CDN_LAST   equ   < 0 - 699>
; Notifications from Open or Save dialog
CDN_INITDONE   equ   < CDN_FIRST - 00000h>
CDN_SELCHANGE   equ   < CDN_FIRST - 00001h>
CDN_FOLDERCHANGE   equ   < CDN_FIRST - 00002h>
CDN_SHAREVIOLATION   equ   < CDN_FIRST - 00003h>
CDN_HELP   equ   < CDN_FIRST - 00004h>
CDN_FILEOK   equ   < CDN_FIRST - 00005h>
CDN_TYPECHANGE   equ   < CDN_FIRST - 00006h>
IF ( NTDDI_VERSION GE  NTDDI_WIN2K)
CDN_INCLUDEITEM   equ   < CDN_FIRST - 00007h>
ENDIF ; (NTDDI_VERSION >= NTDDI_WIN2K)
CDM_FIRST   equ   < WM_USER + 100>
CDM_LAST   equ   < WM_USER + 200>

;-------- and more -------------------

Fa is a musical note to play with CL