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 :wink:

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
spangly wrote:Windows 9x version, download the following dll
http://download.microsoft.com/download/ ... nicows.exe
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 Image

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, :wink: .

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