Sample code to add an XP manifest to a program

Share your advanced PureBasic knowledge/code with the community.
spangly
User
User
Posts: 54
Joined: Mon Apr 28, 2003 8:26 pm
Contact:

Sample code to add an XP manifest to a program

Post 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
User avatar
Inner
PureBasic Expert
PureBasic Expert
Posts: 715
Joined: Fri Apr 25, 2003 4:47 pm
Location: New Zealand

Post by Inner »

nice one thanks :)
GPI
PureBasic Expert
PureBasic Expert
Posts: 1394
Joined: Fri Apr 25, 2003 6:41 pm

Post 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
spangly
User
User
Posts: 54
Joined: Mon Apr 28, 2003 8:26 pm
Contact:

Post 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
GPI
PureBasic Expert
PureBasic Expert
Posts: 1394
Joined: Fri Apr 25, 2003 6:41 pm

Post 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...
spangly
User
User
Posts: 54
Joined: Mon Apr 28, 2003 8:26 pm
Contact:

Post 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.
GPI
PureBasic Expert
PureBasic Expert
Posts: 1394
Joined: Fri Apr 25, 2003 6:41 pm

Post 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).
Seldon
Enthusiast
Enthusiast
Posts: 405
Joined: Fri Aug 22, 2003 7:12 am
Location: Italia

Post 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.
Seldon
Enthusiast
Enthusiast
Posts: 405
Joined: Fri Aug 22, 2003 7:12 am
Location: Italia

Post 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.
Fred
Administrator
Administrator
Posts: 18390
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Post 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 :)
Berikco
Administrator
Administrator
Posts: 1328
Joined: Wed Apr 23, 2003 7:57 pm
Location: Belgium
Contact:

Post 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
Berikco
Seldon
Enthusiast
Enthusiast
Posts: 405
Joined: Fri Aug 22, 2003 7:12 am
Location: Italia

Post 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.
Fred
Administrator
Administrator
Posts: 18390
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Post by Fred »

Seldon: this linker should be ok.
Seldon
Enthusiast
Enthusiast
Posts: 405
Joined: Fri Aug 22, 2003 7:12 am
Location: Italia

Post 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: .
GPI
PureBasic Expert
PureBasic Expert
Posts: 1394
Joined: Fri Apr 25, 2003 6:41 pm

Post 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
Post Reply