News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

How do I go about reading INI files in assembler??

Started by shadow, March 16, 2005, 05:54:38 AM

Previous topic - Next topic

shadow

I have no idea where to start... pls help me..!   Thanks!

pbrennick

shadow,
An ini file is just a test file and can be viewed easily using the ReadFile API.  Download a copy of win32.hlp and read up on it.

Paul

shadow

 :eek (head in hands)  I knew there was an API for that Somewhere!  THANKS!

petezl

Check out "GetPrivateProfileString".  Can't offer any example code cos I'm up to my neck in work at the moment but it's an easy api to use.
Peter.
Cats and women do as they please
Dogs and men should realise it.

Biterider

#4
Hi Shadow!
If you are an ObjAsm32 user, there is an Object called IniFile that handles all ini file read/write tasks.

Regards,
Biterider

pbrennick

ObjAsm32, I think it is a good idea for everyone to explore this excellent tool.  It makes sense to use every resource you can put your hans on.  At some point, I will have to join the mad rush so I can get up to speed in terms of helping others.

Paul

P1

shadow,

I use the system win.ini for passing simple stuff from a MASM32 program into a VB one.

invoke WriteProfileString, addr szSection, addr szKey, addr szLine
30  If GetProfileString("Equipment Return Form", "Current Document", "\\Server\EquipmentRtn\Error.DOC", buffer, Length) Then

You will need to look up the references, to code the reverse of this.

Regards,  P1  :8)

Mark Jones

Hi, here's a way to use the Get/WritePrivateProfileStruct routine to save and load complete structures to and from an .ini file. Build as 'console assemble and link.' Files and RadASM project at bottom.


;  .ini file structure read/write example by Mark Jones 2005
include masm32rt.inc                                ; MASM32 v8.2 SP2a+ RTL's

.data                                               ; preinitialized (file) vars
    iniName     db  '\test.ini',0                   ; file to create
    iniSection  db  'MyApp',0                       ; section text
    iniKey      db  'OFN1',0                        ; key text
   
    ofnFilter   db  'All Files',0,'*.*',0,0         ; OpenFileName filter
    ofnTitle    db  'Select a File',0               ; OpenFileName title

.data?                                              ; runtime (ram) variables
    hConsole    dd  ?                               ; handle of console app
    CurrentDir  db  256 dup(?)                      ; path to .ini file
    OFN1        OPENFILENAME<>                      ; used with GetOpenFileName
    ofnPath     db  256 dup(?)                      ; path to OFN file
    OFN2        OPENFILENAME<>                      ; structure to be filled
   
.code
main:
    invoke GetStdHandle,hConsole                    ; get console handle
    invoke GetCurrentDirectory,255,addr CurrentDir  ; get current dir
    invoke lstrcat,addr CurrentDir,addr iniName     ; append filename to it
   
    mov OFN1.lStructSize,sizeof OFN1                ; setup "open file" struct
    m2m OFN1.hwndOwner,hConsole                     ; 'm2m' is a macro
;   m2m OFN1.hInstance,hInstance                    ; not applicable
    mov OFN1.lpstrFilter,offset ofnFilter           ; file filter
    mov OFN1.lpstrFile,offset ofnPath               ; file path
    mov OFN1.lpstrTitle,offset ofnTitle             ; title
    mov OFN1.nMaxFile,255                           ; reserve a null
    mov OFN1.Flags,OFN_HIDEREADONLY or OFN_NOREADONLYRETURN
   
    print chr$(" Console .ini file test by MCJ 2005",13,10)
    mov eax,input(13,10," Press enter to create test.ini file:")
    call writeit
    mov eax,input(13,10," Press enter to display test.ini:")
    invoke ShellExecute,hConsole,0,addr CurrentDir,0,0,SW_SHOW
    mov eax,input(13,10," Press enter to read test.ini file:")
    call readit
    mov eax,input(13,10," Press enter to use read structure:")
@@:
    invoke GetOpenFileName,offset OFN2              ; ask for a file
    .if eax==0                                      ; if nothing returned,
        invoke Beep,100,1000                        ; complain...
        jmp @B                                      ; and ask again :)
    .endif
    print chr$(13,10," Selected file: ")            ; OFN2.lpstrFile is
    print OFN2.lpstrFile                            ; already a pointer
    print chr$(13,10)                               ; so ADDR is not needed
    mov eax,input(13,10," Press enter to exit.")
    invoke ExitProcess,0                            ; exit gracefully


writeit proc                                        ; write ini file
    invoke WritePrivateProfileStruct,addr iniSection,addr iniKey,\
           addr OFN1,OFN1.lStructSize,addr CurrentDir
    .if eax==0                                      ; if there was an error,
        invoke Beep,100,1000                        ; let us know
    .endif
    ret
writeit endp

readit  proc                                        ; read ini file
    invoke GetPrivateProfileStruct,addr iniSection,addr iniKey,\
           addr OFN2,OFN1.lStructSize,addr CurrentDir
    .if eax==0
        invoke Beep,100,1000
    .endif
    ret
readit  endp


end main

[attachment deleted by admin]
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

hutch--

In the current service pack for MASM32 tere is an example called GETINI that shows how its done.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Mark Jones

That's another interesting way to do it. :)

The idea with Get/WritePrivateProfileStruct was to buffer all of an application's control states, edit box contents, etc. into one struct, then saving that to the .ini file... sounds nice and clean and tidy, no?
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

PBrennick

The GeneSys Project is available from:
The Repository or My crappy website

Mark Jones

 It looks like GetPrivateProfileString only returns single-line strings, even though WritePrivateProfileString will write multiple-line strings... ::) As soon as a CR+LF is encountered, the string is truncated. There appears to be no way around this. Example .ini file:


[MyApp]
settings=1601001700010001
edit1="; hello world...
; test 123
; test 4
; hi there!"


edit1 is returned as:


    "; hello world...


So, here's a similar function which reads keys of any arbitrary length. I named it GetPrivateProfileStringML, ML for multi-line. It's a beta, so... :bg


GetPrivateProfileStringML   proc uses edi esi lpSection:DWORD,lpKey:DWORD,lpDefault:DWORD,lpBuffer:DWORD,nSize:DWORD,lpFile:DWORD
    invoke CreateFile,lpFile,GENERIC_READ,FILE_SHARE_READ,\
                        0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, 0 ; handle in eax
    mov hOpenFile,eax
    .if eax!=INVALID_HANDLE_VALUE               ; if file is valid
        invoke GetFileSize,hOpenFile,0          ; get lpFile size
        inc eax                                 ; add one (null)
        mov nFileSize,eax                       ; save value
        invoke LocalAlloc,GPTR,eax              ; allocate that much ram
        mov hMem,eax                            ; save memory offset
        invoke ReadFile,hOpenFile,hMem,nFileSize,addr hOpenFileSize,0

        mov edi,hMem                            ; source pointer
        mov esi,lpSection                       ; search pointer
begin:                                          ; loop until "[" found
        mov al,byte ptr [edi]                   ; fetch source byte
        inc edi                                 ; increment source pointer
        cmp al,"["                              ; is it a "["
        jz @F                                   ; if found, break
        cmp al,00                               ; else is it a null?
        jz copydef                              ; if so, section not found!
        jmp begin                               ; else loop
@@:                                             ; "[" found
        mov al,byte ptr [edi]                   ; fetch source byte
        mov ah,byte ptr [esi]                   ; fetch section byte
        cmp al,"]"                              ; if we've reached "]" w/o err
        jz @F                                   ; sections match!
        inc esi                                 ; increment pointers
        inc edi                                 ;
        cmp al,ah                               ; compare bytes
        jz  @B                                  ; loop until a difference found
        jmp begin                               ; if none match, search again
@@:                                             ; sections match!
        add edi,3                               ; skip over "]" and CR+LF
        mov esi,lpKey                           ; get pointer of key to find
findit:                                         ; find lpKey within lpSection
        mov al,byte ptr [edi]                   ; fetch source byte
        mov ah,byte ptr [esi]                   ; fetch key byte
        cmp al,"="                              ; if we've reached "=" w/o err
        jz found                                ; keys match
        cmp al,"["                              ; if we found another section,
        jz copydef                              ; key not found
        cmp al,00                               ; if we read a null,
        jz copydef                              ; something terribly wrong
        inc esi                                 ; increment pointers
        inc edi                                 ;
        cmp al,ah                               ; compare bytes
        jz  findit                              ; loop until a difference found
@@:                                             ; no match, goto next line
        mov al,byte ptr [edi]                   ; fetch source byte
        inc edi                                 ; increment pointer
        cmp al,10                               ; LF char?
        jnz @B                                  ; loop while not LF
        mov esi,lpKey                           ; reset key pointer
        jmp findit                              ; try key search again
found:                                          ; key matched!
        inc edi                                 ; skip over "="
        mov esi,lpBuffer                        ; esi as output ptr
@@:                                             ; copy data src to dest
        mov al,byte ptr [edi]                   ; fetch source byte
        cmp al,"="                              ; if we've found another key,
        jz @F                                   ; erase its name from output
        cmp al,"["                              ; if we've found another section,
        jz nullify                              ; just terminate output string
        mov byte ptr [esi],al                   ; put byte in dest buffer
        inc edi                                 ; increment pointers
        inc esi                                 ;
        test al,al                              ; if it was a null,
        jz done                                 ; we're done
        jmp @B                                  ; else keep copying
@@:                                             ; erase last xxxx= from buffer
        mov al,byte ptr [esi]                   ; fetch destination byte
        mov byte ptr [esi],00                   ; overwrite with a null
        dec esi                                 ; decrement dest pointer
        cmp al,13                               ; was last byte a CR?
        jnz @B                                  ; loop until last line is deleted
        jmp done                                ; we're done. :)
nullify:                                        ; if a last null is needed
        mov byte ptr [esi],00                   ; output a null
        jmp done                                ;
copydef:                                        ; else copy lpDefault
        mov edi,lpDefault                       ; default as source ptr
@@:                                             ; loop until string copied
        mov al,byte ptr [edi]                   ; fetch source byte
        mov byte ptr [esi],al                   ; output
        test al,al                              ; was byte a null?
        jnz @B                                  ; loop intil null copied
done:                                           ; we're done!
        mov eax,1                               ; return "good" value
        invoke LocalFree,hMem                   ; free memory
    .else                                       ; or if error opening file
        mov eax,0                               ; return "error" value
    .endif

    .if hOpenFile!=0                            ; if we have a file handle open,
        invoke CloseHandle,hOpenFile            ; free it
    .endif
    ret
GetPrivateProfileStringML   endp


A properly-spaced copy is attached.

[attachment deleted by admin]
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

Mark Jones

Also seeing that an equals sign in the source string is not allowable using this method, here is a short proc to replace any "=" in the string with something else. :)


RemoveEqualsFromStr proc uses esi lpString:DWORD; removes "=" char from str
    mov esi,lpString                            ; pointer as esi
    dec esi                                     ; align properly
@@:                                             ; loop until null found
    inc esi                                     ; increment pointer
    cmp byte ptr [esi],00                       ; byte a null?
    jz @F                                       ; if so, done
    cmp byte ptr [esi],"="                      ; is byte an "="?
    jnz @B                                      ; loop while not "="
    mov byte ptr [esi],":"                      ; else replace "=" with ":"
    jmp @B                                      ; continue until null
@@:
    ret
RemoveEqualsFromStr endp
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

Mark Jones

Updated version of RemoveEqualsFromStr. Now removes any trailiing CR+LFs. :)


RemoveEqualsFromStr proc uses esi lpString:DWORD; removes "=" char from str
    mov esi,lpString                            ; pointer(-1) as esi
    dec esi                                     ; align properly
@@:                                             ; loop until null found
    inc esi                                     ; increment pointer
    cmp byte ptr [esi],00                       ; byte a null?
    jz @F                                       ; if so, done
    cmp byte ptr [esi],"="                      ; is byte an "="?
    jnz @B                                      ; loop while not "="
    mov byte ptr [esi],":"                      ; else replace "=" with ":"
    jmp @B                                      ; continue until null
@@:                                             ; strip off any trailing returns
    sub esi,2                                   ; backup pointer two bytes
    cmp byte ptr [esi],13                       ; is there an ending CR+LF?
    jz killit
    ret
killit:
    mov word ptr [esi],0000                     ; buh-bye!
    jmp @B                                      ; check for more
RemoveEqualsFromStr endp
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

shadow

Quote from: Mark Jones on August 05, 2005, 07:02:38 PM
It looks like GetPrivateProfileString only returns single-line strings, even though WritePrivateProfileString will write multiple-line strings... ::) As soon as a CR+LF is encountered, the string is truncated. There appears to be no way around this.

I'm realizing this halfway through writing my CD autorun menu program.  :red  Thanks Mark! :cheekygreen: I'll try that... you're a genius!  -pat on back-