I have no idea where to start... pls help me..! Thanks!
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
:eek (head in hands) I knew there was an API for that Somewhere! THANKS!
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.
Hi Shadow!
If you are an ObjAsm32 user, there is an Object called IniFile that handles all ini file read/write tasks.
Regards,
Biterider
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
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)
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]
In the current service pack for MASM32 tere is an example called GETINI that shows how its done.
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?
Yes. :U
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]
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
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
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-