Page 1 of 2
Sample code to add an XP manifest to a program
Posted: Sat Aug 16, 2003 2:29 pm
by spangly
The following code is an example of how to add the XP manifest file to you program, it could be adapted to add anything you like to the resource section of any program. There isn't much error checking, but I've added comments so you know what's going on
Code: Select all
#RT_MANIFEST = 24
#LANG_ID = $0809 ; English (United Kingdom)
; change the following to the name of the exe
filename.s="filename.exe"
manifest.s=filename+".manifest" ; tag the ".manifest" suffix onto the filename
;Get the size of the manifest, allocate some memory and load it in.
size.l=FileSize(manifest)
If size>0
mem.l=AllocateMemory(0,size,0)
ReadFile(0,manifest)
ReadData(mem,size)
CloseFile(0)
EndIf
; Warning, if the manifest already exists, it will be overwritten !
hUpdateRes = BeginUpdateResource_(filename, FALSE)
; if hUpdateRes = 0 then error occured
result = UpdateResource_(hUpdateRes,#RT_MANIFEST,1,#LANG_ID,mem,size)
; if result = 0 then an error occured
result = EndUpdateResource_(hUpdateRes, #FALSE)
; if result = 0 then an error occured
FreeMemory(0)
End
Posted: Sat Aug 16, 2003 2:43 pm
by Inner
nice one thanks

Posted: Sat Aug 16, 2003 3:55 pm
by GPI
Will not work under Win9x (ok, there you don't need a manifest, but i work primary on Win98SE)
p.s.: jaPBe can also include the manifest. I do this with resourcehacker.
GPI
Posted: Sat Aug 16, 2003 4:55 pm
by spangly
Windows 9x version, download the following dll
http://download.microsoft.com/download/ ... nicows.exe
it's the microsft layer for unicode on win9x
and use the following code instead
Code: Select all
#RT_MANIFEST = 24
#LANG_ID = $0809 ; English (United Kingdom)
; change the following to the name of the exe
filename.s="pbbuild2.exe"
manifest.s=filename+".manifest" ; tag the ".manifest" suffix onto the filename
;Get the size of the manifest, allocate some memory and load it in.
size.l=FileSize(manifest)
If size>0
mem.l=AllocateMemory(0,size,0)
ReadFile(0,manifest)
ReadData(mem,size)
CloseFile(0)
EndIf
OpenLibrary(0,"unicows.dll")
; Warning, if the manifest already exists, it will be overwritten !
hUpdateRes = CallFunction(0,"BeginUpdateResourceA",@filename, #FALSE)
; if hUpdateRes = 0 then error occured
result = CallFunction(0,"UpdateResourceA",hUpdateRes,#RT_MANIFEST,1,#LANG_ID,mem,size)
; if result = 0 then an error occured
result = CallFunction(0,"EndUpdateResourceA",hUpdateRes, #FALSE)
; if result = 0 then an error occured
FreeMemory(0)
CloseLibrary(0)
End
Posted: Sat Aug 16, 2003 9:45 pm
by GPI
Yes, but not the best solution for me.
At the moment you must only dezip to files in the same directory. When i use your methode, you must unzip the files AND install the exe. And for this feature, you must install this, and this, and this...
Posted: Sun Aug 17, 2003 12:24 am
by spangly
You can put the unicows.dll in the same directory as your exe, it doesn't need to be installed, that's how I tested it on my 98se partition, and the only place the dll exists is in the same dir as my source code.
Posted: Thu Aug 21, 2003 8:56 pm
by GPI
totally useless (for win98se), or i have a bug in my example-programm:
Code: Select all
Global UpdateResourceHandle_
Global BeginUpdateResource_,UpdateResource_,EndUpdateResource_
Procedure BeginUpdateResource(FileName,DeleteExistingResources)
If GetVersion_() & $ff0000
Result=BeginUpdateResource_(FileName,DeleteExistingResources)
Else
UpdateResourceHandle_=API_OpenLibrary("unicows.dll")
If UpdateResourceHandle_
BeginUpdateResource_=API_IsFunction(UpdateResourceHandle_,"BeginUpdateResourceA")
UpdateResource_ =API_IsFunction(UpdateResourceHandle_,"UpdateResourceA")
EndUpdateResource_ =API_IsFunction(UpdateResourceHandle_,"EndUpdateResourceA")
Result = CallFunctionFast(BeginUpdateResource_,FileName,DeleteExistingResources)
EndIf
EndIf
ProcedureReturn Result
EndProcedure
Procedure UpdateResource(Handle,Type,Name,Langid,Buffer,Len)
If GetVersion_() & $ff0000
Result=UpdateResource_(Handle,Type,Name,Langid,Buffer,Len)
Else
If UpdateResourceHandle_
Result = CallFunctionFast(UpdateResource_,Handle,Type,Name,Langid,Buffer,Len)
EndIf
EndIf
ProcedureReturn Result
EndProcedure
Procedure EndUpdateResource(Handle,WriteFlag)
If GetVersion_() & $ff0000
Result=EndUpdateResource_(Handle,WriteFlag)
Else
If UpdateResourceHandle_
Result = CallFunctionFast(EndUpdateResource_,Handle,WriteFlag)
API_FreeLibrary(UpdateResourceHandle_)
UpdateResourceHandle_=0
EndIf
EndIf
ProcedureReturn Result
EndProcedure
#RT_RCDATA = 10
#RT_ICON = 3
#DIFFERENCE = 11
#RT_MANIFEST = 24
#RT_GROUP_ICON = (#RT_ICON + #DIFFERENCE)
File$="test.exe.manifest"
Len=FileSize(File$)
#LANG_ID = $0809 ; English (United Kingdom)
Debug Len
If Len>0
adr=AllocateMemory(1,Len+1)
If ReadFile(0,File$)
ReadData(adr,Len)
CloseFile(0)
DeleteFile("test2.exe")
CopyFile("test.exe","Test2.exe")
Handle= BeginUpdateResource(@"test2.exe",#False):Debug Handle
a$="Hallo"
Debug UpdateResource(Handle,#RT_RCDATA,1,0,@a$,Len(a$))
;Debug UpdateResource(Handle,#RT_MANIFEST,1,#LANG_ID,adr,Len)
Debug EndUpdateResource(Handle,#False)
FreeMemory(1)
EndIf
EndIf
End
I get only currupted executes (win98SE).
Posted: Tue Nov 11, 2003 10:30 am
by Seldon
I'm trying to use the UNICOWS.DLL under Win98SE, the DLL does open, but the Handle from BeginUpdateResource is always 0 :roll: . Here it is my code, have you any suggestion ? Thank you in advance.
Code: Select all
#RT_RCDATA=10
UseJPEGImageDecoder()
UsePNGImageDecoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()
Global hUpdateRes
Global *mem0
Global NamePlug$
Global lun_res
Procedure BeginU(ver_so)
If ver_so
hUpdateRes=BeginUpdateResource_(@NamePlug$,#FALSE)
Else
hUpdateRes=CallFunction(0,"BeginUpdateResourceA",@NamePlug$,#FALSE)
PrintN(Str(hUpdateRes))
EndIf
EndProcedure
Procedure UpdateR(ver_so)
If ver_so
result=UpdateResource_(hUpdateRes,#RT_RCDATA,1,0,*mem0,lun_res)
Else
result=CallFunction(0,"UpdateResourceA",hUpdateRes,#RT_RCDATA,1,0,UseMemory(1),lun_res)
;result=CallFunction(0,"UpdateResourceA",hUpdateRes,#RT_RCDATA,1,0,*mem0,lun_res)
PrintN(Str(result))
EndIf
EndProcedure
Procedure EndU(ver_so)
If ver_so
result=EndUpdateResource_(hUpdateRes,#FALSE)
Else
result=CallFunction(0,"EndUpdateResourceA",hUpdateRes,#FALSE)
EndIf
EndProcedure
ver_so=GetVersion_() & $ff0000
If ver_so=0
res=OpenLibrary(0,"unicows.dll")
EndIf
If res
; FileName$=ProgramParameter()
; Opzione$=ProgramParameter()
; NamePlug$=ProgramParameter()
FileName$="test.bmp"
NamePlug$="gfxdll.dll"
OpenConsole()
;Print (Str(ver_so))
;r$=Input()
ImageHandle=LoadImage(0,FileName$)
If ImageHandle
larghezza=ImageWidth()
altezza=ImageHeight()
SizeOfMem=larghezza*altezza*4+9
iByte8=0
iBankPointer=9
*mem0=AllocateMemory(0,SizeOfMem,0)
PokeL(*mem0,larghezza)
PokeL(*mem0+4,altezza)
PokeB(*mem0+8,iByte8)
PrintN("")
Print("Conversion: [")
ImageDC=ImageOutput()
StartDrawing(ImageDC)
For iLoopX=0 To larghezza-1
For iLoopY=0 To altezza-1
rgb=Point(iLoopX,iLoopY)
*pointer=@rgb
red.b=PeekB(*pointer)
ver.b=PeekB(*pointer+1)
blu.b=PeekB(*pointer+2)
PokeB(*mem0+iBankPointer,blu.b)
PokeB(*mem0+iBankPointer+1,ver.b)
PokeB(*mem0+iBankPointer+2,red.b)
PokeB(*mem0+iBankPointer+3,255)
iBankPointer+4
Next
Print(".")
Next
StopDrawing()
PrintN("]")
CreateFile(1,"prova")
WriteData(*mem0,SizeOfMem)
CloseFile(1)
If Opzione$<>"/nc"
Print("Compression: [")
AllocateMemory(1,SizeOfMem+8,0)
CompressedLength=PackMemory(UseMemory(0),UseMemory(1),SizeOfMem+8)
PrintN("]")
lun_res=CompressedLength
Else
CompressedLength=0
lun_res=SizeOfMem
EndIf
BeginU(ver_so)
UpdateR(ver_so)
EndU(ver_so)
i.b=FindString(FileName$,".",0)
tmp$=Mid(FileName$,0,i.b)+"vsp"
CreateFile(0,tmp$)
WriteLong(SizeOfMem) ;scrive la lunghezza del file originale
;WriteString(FileName$)
If CompressedLength
WriteData(UseMemory(1),CompressedLength) ;scrive la parte compressa
Else
WriteData(*mem0,SizeOfMem)
EndIf
CloseFile(0)
FreeMemory(1)
FreeMemory(0)
CloseLibrary(0)
PrintN("Image has been converted successfully.")
CloseConsole()
a$=Input()
EndIf
Else
PrintN("UNICOWS.DLL not found.")
EndIf
End
The file gfxdll.dll is in the same path. Could someone try it on WinNT+ and see if it works ? Of course you must change the content of NamePlug$ string with the name of a file of yours. Thanks.
Posted: Wed Nov 12, 2003 2:40 pm
by Seldon
Tiny update: now I get get a valid handle, by changing the flag in BeginUpdateResource() from #FALSE to #TRUE (if no resource already taked place in the file, it must be set to #TRUE). The file (I tried both EXEs and DLLs) is updated, but it's corrupt.
Posted: Wed Nov 12, 2003 3:01 pm
by Fred
New LccLinker allow to add this directly in the exe. So a little linker wrapper would do it easily. It will be done for the next version so this willn't be an issue anymore

Posted: Wed Nov 12, 2003 3:43 pm
by Berikco
Fred wrote:New LccLinker allow to add this directly in the exe. So a little linker wrapper would do it easily. It will be done for the next version so this willn't be an issue anymore

Yipieee

Posted: Wed Nov 12, 2003 5:25 pm
by Seldon
Thanks for hint, Fred. So, it means you can add any .RES (compiled resource) into an EXE ? That's great. I have the last built of lcc as well (Nov. 9), but still it has lcclnk ver.1.3 . Is the new linker ready yet? I really would need it before the new version of PB.
Posted: Wed Nov 12, 2003 6:43 pm
by Fred
Seldon: this linker should be ok.
Posted: Wed Nov 12, 2003 9:44 pm
by Seldon
You see, my problem is that I must add some resources to a DLL made with PB. Since the DLL has NO icon, ResHacker isn't able to update the file (it does, but the DLL is corrupted -> it's a bug). In C, I'd simply pass my resource compiled file (.RES) and the main object file (.O) to a linker. But with PB ? How can I have my .RES file linked into the final PB .EXE ?
Thanks for your time,

.
Posted: Thu Nov 13, 2003 7:09 pm
by GPI
Fred wrote:Seldon: this linker should be ok.
A complete user use of the linker would be nice. I want to add additional icons (for file associate), Version-Information and other resources...
GPI