DirectX Hook?
DirectX Hook?
Does anyone have any PB code for hooking directX? I've seen the stuff in the forums about hooks but DirectX is such a new subject to me I don't see the connection between whats in the forums for other types of hooks and directX.
Last edited by SFSxOI on Sun Apr 02, 2006 3:14 pm, edited 1 time in total.
Re: DirectX Hook?
Can't offer you PB code but here are two links:
http://www.gamedev.net/community/forums ... _id=359794
http://pc.nanobot2k.org/Tutorials/D3DHookPack.zip
http://www.gamedev.net/community/forums ... _id=359794
http://pc.nanobot2k.org/Tutorials/D3DHookPack.zip
Good programmers don't comment their code. It was hard to write, should be hard to read.
-
- Addict
- Posts: 2344
- Joined: Mon Jun 02, 2003 9:16 am
- Location: Germany
- Contact:
Launcher:
my_ddraw.dll:
RemoteAPI:
RemoteAPI - Hook v.1.1
Don't know if it still works, but should. It was to hook Age of Empires II, but I didn't finish it because AoE II needs to run in 8 bit color mode and I wanted to run it in window, but I noticed the mode too late.
Code: Select all
Procedure GetKernelAddress(funktion.s)
hKernel=LoadLibrary_("kernel32.dll")
func=GetProcAddress_(hKernel,funktion)
FreeLibrary_(hKernel)
ProcedureReturn func
EndProcedure
Procedure RemoteGetProcAddress_(DLL_intern.l,funktion.s,DLL_extern.l)
func=GetProcAddress_(DLL_intern,funktion)
If func
ProcedureReturn (func-DLL_intern)+DLL_extern
EndIf
EndProcedure
If OpenLibrary(0,"remoteapi.dll")=0
MessageRequester("ERROR", "remoteapi.dll not found - Canceled")
End
EndIf
FileName.s=OpenFileRequester("Select the executable","","*.exe",0)
If FileName=""
MessageRequester("ERROR", "No file selected - Canceled")
End
EndIf
sinfo.STARTUPINFO
sinfo\cb=SizeOf(STARTUPINFO)
pinfo.PROCESS_INFORMATION
If CreateProcess_(0,FileName,0,0,0,#CREATE_SUSPENDED,0,0,@sinfo.STARTUPINFO,@pinfo.PROCESS_INFORMATION)=0
MessageRequester("ERROR", "Unable to load exe - Canceled")
End
EndIf
If CallFunction(0,"RemoteAPIInit",pinfo\hProcess,pinfo\hThread)=0
MessageRequester("ERROR", "Unable to set current process/thread - Canceled")
End
EndIf
MyFileName.s=Space(1024)
GetModuleFileName_(0,@MyFileName.s,1024)
MyFilePath.s=GetPathPart(MyFileName)
If Right(MyFilePath,1)<>"\"
MyFilePath+"\"
EndIf
DLL_name.s=MyFilePath+"my_ddraw.dll"
DLL_intern=LoadLibrary_(DLL_name)
CallFunction(0,"RemoteAPIAdd",@DLL_name,Len(DLL_name)+1)
DLL_extern = CallFunction(0,"RemoteAPIExec",GetKernelAddress("LoadLibraryA"),1)
If DLL_intern=0 Or DLL_extern=0
MessageRequester("ERROR", "Loading dll failed")
ResumeThread_(pinfo\hThread)
End
EndIf
CallFunction(0,"RemoteAPIAdd",DLL_extern,0)
result = CallFunction(0,"RemoteAPIExec",RemoteGetProcAddress_(DLL_intern,"StartHook",DLL_extern),2)
If result=0
MessageRequester("ERROR", "Hooking failed :(")
EndIf
ResumeThread_(pinfo\hThread)
Code: Select all
Structure wAPI_func
GetProcAddress.l
LoadLibraryA.l
LoadLibraryW.l
LoadLibraryExA.l
LoadLibraryExW.l
DirectDrawCreateEx.l
ReplaceAdd.l
ReplaceExec.l
ReplaceExecEx.l
EndStructure
Structure DDraw
SetCooperativeLevel.l
SetDisplayMode.l
CreateSurface.l
CreateClipper.l
SetClipper.l
EndStructure
Global wAPI.wAPI_func, Me.l, Old.DDraw, Window
;/ remoteapi.dll Commands
Procedure ReplaceAdd(OldAddress.l,NewAddress.l)
ProcedureReturn CallFunctionFast(wAPI\ReplaceAdd,OldAddress,NewAddress)
EndProcedure
Procedure ReplaceExec(ProcessBase.l)
ProcedureReturn CallFunctionFast(wAPI\ReplaceExec,ProcessBase.l)
EndProcedure
Procedure ReplaceExecEx(Address.l)
ProcedureReturn CallFunctionFast(wAPI\ReplaceExecEx,Address.l)
EndProcedure
;/ new Library Commands
#DONT_RESOLVE_DLL_REFERENCES =$00000001
#LOAD_LIBRARY_AS_DATAFILE =$00000002
#LOAD_WITH_ALTERED_SEARCH_PATH =$00000008
#DDSCL_FULLSCREEN = $00000001
#DDSCL_ALLOWREBOOT = $00000002
#DDSCL_NOWINDOWCHANGES = $00000004
#DDSCL_NORMAL = $00000008
#DDSCL_EXCLUSIVE = $00000010
#DDSCL_ALLOWMODEX = $00000040
#DDSCL_SETFOCUSWINDOW = $00000080
#DDSCL_SETDEVICEWINDOW = $00000100
#DDSCL_CREATEDEVICEWINDOW = $00000200
#DDSCL_MULTITHREADED = $00000400
#DDSCL_FPUSETUP = $00000800
#DDSCL_FPUPRESERVE = $00001000
#DDSD_CAPS = $00000001
#DDSD_HEIGHT = $00000002
#DDSD_WIDTH = $00000004
#DDSD_PITCH = $00000008
#DDSD_BACKBUFFERCOUNT = $00000020
#DDSD_ZBUFFERBITDEPTH = $00000040
#DDSD_ALPHABITDEPTH = $00000080
#DDSD_LPSURFACE = $00000800
#DDSD_PIXELFORMAT = $00001000
#DDSD_CKDESTOVERLAY = $00002000
#DDSD_CKDESTBLT = $00004000
#DDSD_CKSRCOVERLAY = $00008000
#DDSD_CKSRCBLT = $00010000
#DDSD_MIPMAPCOUNT = $00020000
#DDSD_REFRESHRATE = $00040000
#DDSD_LINEARSIZE = $00080000
#DDSD_TEXTURESTAGE = $00100000
#DDSD_FVF = $00200000
#DDSD_SRCVBHANDLE = $00400000
#DDSD_ALL = $007ff9ee
#DD_ROP_SPACE = (256/32)
#DDSCAPS_RESERVED1 = $00000001
#DDSCAPS_ALPHA = $00000002
#DDSCAPS_BACKBUFFER = $00000004
#DDSCAPS_COMPLEX = $00000008
#DDSCAPS_FLIP = $00000010
#DDSCAPS_FRONTBUFFER = $00000020
#DDSCAPS_OFFSCREENPLAIN = $00000040
#DDSCAPS_OVERLAY = $00000080
#DDSCAPS_PALETTE = $00000100
#DDSCAPS_PRIMARYSURFACE = $00000200
#DDSCAPS_RESERVED3 = $00000400
#DDSCAPS_SYSTEMMEMORY = $00000800
#DDSCAPS_TEXTURE = $00001000
#DDSCAPS_3DDEVICE = $00002000
#DDSCAPS_VIDEOMEMORY = $00004000
#DDSCAPS_VISIBLE = $00008000
#DDSCAPS_WRITEONLY = $00010000
#DDSCAPS_ZBUFFER = $00020000
#DDSCAPS_OWNDC = $00040000
#DDSCAPS_LIVEVIDEO = $00080000
#DDSCAPS_HWCODEC = $00100000
#DDSCAPS_MODEX = $00200000
#DDSCAPS_MIPMAP = $00400000
#DDSCAPS_RESERVED2 = $00800000
#DDSCAPS_ALLOCONLOAD = $04000000
#DDSCAPS_VIDEOPORT = $08000000
#DDSCAPS_LOCALVIDMEM = $10000000
#DDSCAPS_NONLOCALVIDMEM = $20000000
#DDSCAPS_STANDARDVGAMODE = $40000000
#DDSCAPS_OPTIMIZED = $80000000
#DDSCAPS2_HARDWAREDEINTERLACE = $00000002
#DDSCAPS2_HINTDYNAMIC = $00000004
#DDSCAPS2_HINTSTATIC = $00000008
#DDSCAPS2_TEXTUREMANAGE = $00000010
#DDSCAPS2_RESERVED1 = $00000020
#DDSCAPS2_RESERVED2 = $00000040
#DDSCAPS2_OPAQUE = $00000080
#DDSCAPS2_HINTANTIALIASING = $00000100
#DDSCAPS2_CUBEMAP = $00000200
#DDSCAPS2_CUBEMAP_POSITIVEX = $00000400
#DDSCAPS2_CUBEMAP_NEGATIVEX = $00000800
#DDSCAPS2_CUBEMAP_POSITIVEY = $00001000
#DDSCAPS2_CUBEMAP_NEGATIVEY = $00002000
#DDSCAPS2_CUBEMAP_POSITIVEZ = $00004000
#DDSCAPS2_CUBEMAP_NEGATIVEZ = $00008000
#DDSCAPS2_CUBEMAP_ALLFACES = ( #DDSCAPS2_CUBEMAP_POSITIVEX | #DDSCAPS2_CUBEMAP_NEGATIVEX | #DDSCAPS2_CUBEMAP_POSITIVEY | #DDSCAPS2_CUBEMAP_NEGATIVEY | #DDSCAPS2_CUBEMAP_POSITIVEZ | #DDSCAPS2_CUBEMAP_NEGATIVEZ )
#DDSCAPS2_MIPMAPSUBLEVEL = $00010000
#DDSCAPS2_D3DTEXTUREMANAGE = $00020000
#DDSCAPS2_DONOTPERSIST = $00040000
#DDSCAPS2_STEREOSURFACELEFT = $00080000
Structure DDCOLORKEY
dwColorSpaceLowValue.l
dwColorSpaceHighValue.l
EndStructure
Structure DDPIXELFORMAT
dwSize.l; // size of structure
dwFlags.l; // pixel format flags
dwFourCC.l; // (FOURCC code)
StructureUnion
dwRGBBitCount.l; // how many bits per pixel
dwYUVBitCount.l; // how many bits per pixel
dwZBufferBitDepth.l; // how many total bits/pixel in z buffer (including any stencil bits)
dwAlphaBitDepth.l; // how many bits for alpha channels
dwLuminanceBitCount.l; // how many bits per pixel
dwBumpBitCount.l; // how many bits per "buxel", total
EndStructureUnion
StructureUnion
dwRBitMask.l; // mask for red bit
dwYBitMask.l; // mask for Y bits
dwStencilBitDepth.l; // how many stencil bits (note: dwZBufferBitDepth-dwStencilBitDepth is total Z-only bits)
dwLuminanceBitMask.l; // mask for luminance bits
dwBumpDuBitMask.l; // mask for bump map U delta bits
EndStructureUnion
StructureUnion
dwGBitMask.l; // mask for green bits
dwUBitMask.l; // mask for U bits
dwZBitMask.l; // mask for Z bits
dwBumpDvBitMask.l; // mask for bump map V delta bits
EndStructureUnion
StructureUnion
dwBBitMask.l; // mask for blue bits
dwVBitMask.l; // mask for V bits
dwStencilBitMask.l; // mask for stencil bits
dwBumpLuminanceBitMask.l; // mask for luminance in bump map
EndStructureUnion
StructureUnion
dwRGBAlphaBitMask.l; // mask for alpha channel
dwYUVAlphaBitMask.l; // mask for alpha channel
dwLuminanceAlphaBitMask.l; // mask for alpha channel
dwRGBZBitMask.l; // mask for Z channel
dwYUVZBitMask.l; // mask for Z channel
EndStructureUnion
EndStructure
Structure DDSCAPS2
dwCaps.l ;// capabilities of surface wanted
dwCaps2.l
dwCaps3.l
dwCaps4.l
EndStructure
Structure DDSURFACEDESC2
dwSize.l; // size of the DDSURFACEDESC structure
dwFlags.l; // determines what fields are valid
dwHeight.l; // height of surface to be created
dwWidth.l; // width of input surface
StructureUnion
lPitch.l; // distance to start of next line (return value only)
dwLinearSize.l; // Formless late-allocated optimized surface size
EndStructureUnion
dwBackBufferCount.l; // number of back buffers requested
StructureUnion
dwMipMapCount.l; // number of mip-map levels requestde
; // dwZBufferBitDepth removed, use ddpfPixelFormat one instead
dwRefreshRate.l; // refresh rate (used when display mode is described)
dwSrcVBHandle.l; // The source used in VB::Optimize
EndStructureUnion
dwAlphaBitDepth.l; // depth of alpha buffer requested
dwReserved.l; // reserved
lpSurface.l; // pointer to the associated surface memory
StructureUnion
ddckCKDestOverlay.DDCOLORKEY; // color key for destination overlay use
dwEmptyFaceColor.l; // Physical color for empty cubemap faces
EndStructureUnion
ddckCKDestBlt.DDCOLORKEY; // color key for destination blt use
ddckCKSrcOverlay.DDCOLORKEY; // color key for source overlay use
ddckCKSrcBlt.DDCOLORKEY; // color key for source blt use
StructureUnion
ddpfPixelFormat.DDPIXELFORMAT; // pixel format description of the surface
dwFVF.l; // vertex format description of vertex buffers
EndStructureUnion
ddsCaps.DDSCAPS2; // direct draw surface capabilities
dwTextureStage.l; // stage in multitexture cascade
EndStructure
Procedure myGetProcAddress(hModule,lpProcName)
ProcedureReturn ReplaceExecEx(CallFunctionFast(wAPI\GetProcAddress,hModule,lpProcName))
EndProcedure
Procedure myLoadLibraryA(lpLibFileName)
base=CallFunctionFast(wAPI\LoadLibraryA,lpLibFileName)
If base
ReplaceExec(base)
EndIf
ProcedureReturn base
EndProcedure
Procedure myLoadLibraryW(lpLibFileName)
base=CallFunctionFast(wAPI\LoadLibraryW,lpLibFileName)
If base
ReplaceExec(base)
EndIf
ProcedureReturn base
EndProcedure
Procedure myLoadLibraryExA(lpLibFileName,hFile,dwFlags)
base=CallFunctionFast(wAPI\LoadLibraryExA,lpLibFileName,hFile,dwFlags)
If base
If (dwFlags&#LOAD_LIBRARY_AS_DATAFILE)=0
If (dwFlags&#DONT_RESOLVE_DLL_REFERENCES)=0
ReplaceExec(base)
EndIf
EndIf
EndIf
ProcedureReturn base
EndProcedure
Procedure myLoadLibraryExW(lpLibFileName,hFile,dwFlags)
base=CallFunctionFast(wAPI\LoadLibraryExW,lpLibFileName,hFile,dwFlags)
If base
If (dwFlags&#LOAD_LIBRARY_AS_DATAFILE)=0
If (dwFlags&#DONT_RESOLVE_DLL_REFERENCES)=0
ReplaceExec(base)
EndIf
EndIf
EndIf
ProcedureReturn base
EndProcedure
;/ other Commands
ProcedureDLL mySetCooperativeLevel(*This, a, b)
If b & #DDSCL_FULLSCREEN
b - #DDSCL_FULLSCREEN
b = #DDSCL_NORMAL
EndIf
; If b & #DDSCL_FULLSCREEN
; Text.s + Chr(10) + "#DDSCL_FULLSCREEN"
; EndIf
; If b & #DDSCL_ALLOWREBOOT
; Text.s + Chr(10) + "#DDSCL_ALLOWREBOOT"
; EndIf
; If b & #DDSCL_NOWINDOWCHANGES
; Text.s + Chr(10) + "#DDSCL_NOWINDOWCHANGES"
; EndIf
; If b & #DDSCL_NORMAL
; Text.s + Chr(10) + "#DDSCL_NORMAL"
; EndIf
; If b & #DDSCL_EXCLUSIVE
; Text.s + Chr(10) + "#DDSCL_EXCLUSIVE"
; EndIf
; If b & #DDSCL_ALLOWMODEX
; Text.s + Chr(10) + "#DDSCL_ALLOWMODEX"
; EndIf
; If b & #DDSCL_SETFOCUSWINDOW
; Text.s + Chr(10) + "#DDSCL_SETFOCUSWINDOW"
; EndIf
; If b & #DDSCL_SETDEVICEWINDOW
; Text.s + Chr(10) + "#DDSCL_SETDEVICEWINDOW"
; EndIf
; If b & #DDSCL_CREATEDEVICEWINDOW
; Text.s + Chr(10) + "#DDSCL_CREATEDEVICEWINDOW"
; EndIf
; If b & #DDSCL_MULTITHREADED
; Text.s + Chr(10) + "#DDSCL_MULTITHREADED"
; EndIf
; If b & #DDSCL_FPUSETUP
; Text.s + Chr(10) + "#DDSCL_FPUSETUP"
; EndIf
; If b & #DDSCL_FPUPRESERVE
; Text.s + Chr(10) + "#DDSCL_FPUPRESERVE"
; EndIf
; MessageRequester("", Text)
; SetClipboardText(Text)
Window = a
Result = CallFunctionFast(Old\SetCooperativeLevel,*This, a, b)
ProcedureReturn Result
EndProcedure
ProcedureDLL mySetDisplayMode(*This, a, b, c, d, e)
;MessageRequester("", Str(a)+Chr(10)+Str(b)+Chr(10)+Str(c)+Chr(10)+Str(d)+Chr(10)+Str(e))
Result = 0;CallFunctionFast(Old\SetDisplayMode,*This, a, b, c, d, e)
ProcedureReturn Result
EndProcedure
ProcedureDLL myCreateSurface(*This, *ddsd.DDSURFACEDESC2, *lpDDSBack.IDIRECTDRAWSURFACE7, *pUnkOuter)
;MessageRequester("", Str(*ddsd\dwFlags))
ddsd.DDSURFACEDESC2
ddsd\dwSize = SizeOf(DDSURFACEDESC2)
ddsd\dwFlags = #DDSD_CAPS
ddsd\ddsCaps\dwCaps = #DDSCAPS_PRIMARYSURFACE
Result = CallFunctionFast(Old\CreateSurface, *This, @ddsd.DDSURFACEDESC2, *lpDDSPrimary.IDIRECTDRAWSURFACE7, *pUnkOuter)
If Result
CallFunctionFast(Old\CreateClipper, *This, 0, *lpClipper.IDIRECTDRAWCLIPPER, 0)
*lpClipper\SetHWnd(0, Window)
*lpDDSPrimary\SetClipper(*lpClipper)
ddsd\dwFlags = #DDSD_CAPS | #DDSD_HEIGHT | #DDSD_WIDTH
ddsd\ddsCaps\dwCaps = #DDSCAPS_OFFSCREENPLAIN
ddsd\dwWidth = 800
ddsd\dwHeight = 600
Result = CallFunctionFast(Old\CreateSurface, *This, @ddsd.DDSURFACEDESC2, *lpDDSBack.IDIRECTDRAWSURFACE7, 0)
If Result <> 0
*lpClipper\Release()
*lpDDSPrimary\Release()
EndIf
EndIf
ProcedureReturn Result
EndProcedure
Procedure myDirectDrawCreateEx(*lpGUID, *lplpDD.long, iid, *pUnkOuter)
Result = CallFunctionFast(wAPI\DirectDrawCreateEx, *lpGUID, @DD, iid, *pUnkOuter)
If *lplpDD
*lplpDD\l=DD
EndIf
OrigMode = 0
*pointer=PeekL(DD)+OffsetOf(IDirectDraw7\SetCooperativeLevel())
Old\SetCooperativeLevel = PeekL(*pointer)
VirtualProtectEx_(GetCurrentProcess_(),*pointer,4,64,@OrigMode) ;64=PAGE_EXECUTE_READWRITE
PokeL(*pointer, @mySetCooperativeLevel())
OrigMode = 0
*pointer=PeekL(DD)+OffsetOf(IDirectDraw7\SetDisplayMode())
Old\SetDisplayMode = PeekL(*pointer)
VirtualProtectEx_(GetCurrentProcess_(),*pointer,4,64,@OrigMode) ;64=PAGE_EXECUTE_READWRITE
PokeL(*pointer, @mySetDisplayMode())
OrigMode = 0
*pointer=PeekL(DD)+OffsetOf(IDirectDraw7\CreateSurface())
Old\CreateSurface = PeekL(*pointer)
VirtualProtectEx_(GetCurrentProcess_(),*pointer,4,64,@OrigMode) ;64=PAGE_EXECUTE_READWRITE
PokeL(*pointer, @myCreateSurface())
OrigMode = 0
*pointer=PeekL(DD)+OffsetOf(IDirectDraw7\CreateClipper())
Old\CreateClipper = PeekL(*pointer)
ProcedureReturn Result
EndProcedure
;/ main function
ProcedureDLL StartHook(myDLLAddress.l)
If myDLLAddress
kernel32=LoadLibrary_("kernel32.dll")
wAPI\GetProcAddress=GetProcAddress_(kernel32,"GetProcAddress")
wAPI\LoadLibraryA=GetProcAddress_(kernel32,"LoadLibraryA")
wAPI\LoadLibraryW=GetProcAddress_(kernel32,"LoadLibraryW")
wAPI\LoadLibraryExA=GetProcAddress_(kernel32,"LoadLibraryExA")
wAPI\LoadLibraryExW=GetProcAddress_(kernel32,"LoadLibraryExW")
ddraw=LoadLibrary_("ddraw.dll")
wAPI\DirectDrawCreateEx=GetProcAddress_(ddraw,"DirectDrawCreateEx")
MyFileName.s=Space(1024)
GetModuleFileName_(myDLLAddress,@MyFileName.s,1024)
Me = myDLLAddress
;Me = LoadLibrary_(MyFileName.s)
MyFilePath.s=GetPathPart(MyFileName)
If Right(MyFilePath,1)<>"\"
MyFilePath+"\"
EndIf
remoteapi=LoadLibrary_(MyFilePath+"remoteapi.dll")
If remoteapi=0
ProcedureReturn 0
EndIf
wAPI\ReplaceAdd=GetProcAddress_(remoteapi,"ReplaceAdd")
wAPI\ReplaceExec=GetProcAddress_(remoteapi,"ReplaceExec")
wAPI\ReplaceExecEx=GetProcAddress_(remoteapi,"ReplaceExecEx")
ReplaceAdd(wAPI\GetProcAddress,@myGetProcAddress())
ReplaceAdd(wAPI\LoadLibraryA,@myLoadLibraryA())
ReplaceAdd(wAPI\LoadLibraryW,@myLoadLibraryW())
ReplaceAdd(wAPI\LoadLibraryExA,@myLoadLibraryExA())
ReplaceAdd(wAPI\LoadLibraryExW,@myLoadLibraryExW())
ReplaceAdd(wAPI\DirectDrawCreateEx,@myDirectDrawCreateEx())
ProcedureReturn ReplaceExec(GetModuleHandle_(0))
EndIf
EndProcedure
RemoteAPI - Hook v.1.1
Don't know if it still works, but should. It was to hook Age of Empires II, but I didn't finish it because AoE II needs to run in 8 bit color mode and I wanted to run it in window, but I noticed the mode too late.
bye,
Daniel
Daniel
DarkDragon,
Thank you for a very fine example. Just one thing i don't understand tho,
what is the 'MyFileName' part??
Thank you for a very fine example. Just one thing i don't understand tho,
Code: Select all
MyFileName.s=Space(1024)
GetModuleFileName_(0,@MyFileName.s,1024)
MyFilePath.s=GetPathPart(MyFileName)
If Right(MyFilePath,1)<>"\"
MyFilePath+"\"
EndIf
-
- Addict
- Posts: 2344
- Joined: Mon Jun 02, 2003 9:16 am
- Location: Germany
- Contact:
-
- Addict
- Posts: 2344
- Joined: Mon Jun 02, 2003 9:16 am
- Location: Germany
- Contact:
In C++ this would be an array. Here it is a empty string(whitespaced) and it receives the filename of your executable(inclusive path) through the WinAPI command. But if you just take a look at the memory it produces, it's nearly the same, but the string is null-terminated, so one char at the end of the string with the value 0.SFSxOI wrote:Ahhh so its like the C++;
MyFileName[MAX_PATH];
??????
bye,
Daniel
Daniel
-
- Addict
- Posts: 2344
- Joined: Mon Jun 02, 2003 9:16 am
- Location: Germany
- Contact:
No, the ASCII char "0" isn't with the value 0, you'll don't see the 0(that's why Chr(0) won't work), it's just that the programming language knows, here ends the string.SFSxOI wrote:So then the resulting string would look like this:
"C:\SomeDir\Somefile.exe0"
(or this?: "C:\SomeDir\Somefile.exe\0" ??? hmmmm???)
and the path to the dll would then look like this:
"C:\SomeDir\my_ddraw.dll"
In an array it would be:
Code: Select all
C
:
\
S
o
m
e
D
i
r
\
S
o
m
e
f
i
l
e
.
e
x
e
Code: Select all
C
:
\
S
o
m
e
D
i
r
\
S
o
m
e
f
i
l
e
.
e
x
e
[NUL]
bye,
Daniel
Daniel