[PB5.0, x64] Stock constant and structure definition
Posted: Tue Dec 18, 2012 5:01 pm
Been playing with a code for creating a mutex on x64 and I think I found a bug.
First problem: It seems that in both x86 and x64 PureBasic, #SECURITY_DESCRIPTOR_MIN_LENGTH is equal to 20. On x86, this is valid, but on x64, the value should be (?) 40 as the size of structure SECURITY_DESCRIPTOR is 40 bytes (longs become integers and there are 4 extra bytes of padding). More info here: http://bugs.freepascal.org/view.php?id=12619).
See my edit below and disregard the following.
Second problem: In PureBasic x64, the structure SECURITY_ATTRIBUTES has 8 bytes of padding. When using it in my code and compile with purifier enabled, the mutex is not created and GetLastError_() returns 998 (Invalid access to memory location). If I disable the purifier, the mutex is successfully created. The strange thing is that if I redefine the structure and eliminate the padding, it works with purifier enabled or disabled. In my opinion, this structure maybe doesn't need padding? I doubt it is a purifier bug.
Here's my code:
[Edit]
I am baffled. The mutex gets created when using the unpadded structure but then OpenMutex fails when trying to open the mutex from another process (denoting bad initialization of the security attributes). 32-bit exes made on x86 from the exact code do work when being run on x64. It's hard to sum it up but there is a problem with memory access somewhere. I got back to using the original, padded PureBasic structure because that's how it should be defined. In the end, found out that if I replace AllocateMemory with LocalAlloc_(), the code works with the purifier enabled. Could it be because of this?
I'd appreciate any input on this issue.
First problem: It seems that in both x86 and x64 PureBasic, #SECURITY_DESCRIPTOR_MIN_LENGTH is equal to 20. On x86, this is valid, but on x64, the value should be (?) 40 as the size of structure SECURITY_DESCRIPTOR is 40 bytes (longs become integers and there are 4 extra bytes of padding). More info here: http://bugs.freepascal.org/view.php?id=12619).
See my edit below and disregard the following.
Second problem: In PureBasic x64, the structure SECURITY_ATTRIBUTES has 8 bytes of padding. When using it in my code and compile with purifier enabled, the mutex is not created and GetLastError_() returns 998 (Invalid access to memory location). If I disable the purifier, the mutex is successfully created. The strange thing is that if I redefine the structure and eliminate the padding, it works with purifier enabled or disabled. In my opinion, this structure maybe doesn't need padding? I doubt it is a purifier bug.
Here's my code:
Code: Select all
Structure SECURITY_ATTRIBUTES_ ;Redefined and eliminated padding
nLength.l
;PB_Alignment1.b[4]
*lpSecurityDescriptor.l
bInheritHandle.l
;PB_Alignment2.b[4]
EndStructure
#SECURITY_DESCRIPTOR_MIN_LENGTH_ = SizeOf(SECURITY_DESCRIPTOR)
Procedure.i CreateMyMutex(Name.s)
Protected Security.SECURITY_ATTRIBUTES ;Replace with Security.SECURITY_ATTRIBUTES_ to make it work with purifier enabled
Protected *Descriptor, hMutex.i, Result.i
*Descriptor = AllocateMemory(#SECURITY_DESCRIPTOR_MIN_LENGTH) ;Replace with #SECURITY_DESCRIPTOR_MIN_LENGTH_ and it works
If *Descriptor <> 0
Security\nLength = SizeOf(SECURITY_ATTRIBUTES) ;Replace with Security.SECURITY_ATTRIBUTES_ to make it work with purifier enabled
Security\bInheritHandle = #False
Security\lpSecurityDescriptor = *Descriptor
If InitializeSecurityDescriptor_(Security\lpSecurityDescriptor, #SECURITY_DESCRIPTOR_REVISION) <> 0
If SetSecurityDescriptorDacl_(Security\lpSecurityDescriptor, #True, 0, #False) <> 0
hMutex = CreateMutex_(@Security, 0, @Name) ;Will overflow due to bad definition of #SECURITY_DESCRIPTOR_MIN_LENGTH
Error = GetLastError_()
Debug "Error: "+Str(Error)
If hMutex <> 0
Result = hMutex
EndIf
EndIf
EndIf
FreeMemory(*Descriptor)
EndIf
ProcedureReturn Result
EndProcedure
Debug "Result: "+Str(CreateMyMutex("test"))
I am baffled. The mutex gets created when using the unpadded structure but then OpenMutex fails when trying to open the mutex from another process (denoting bad initialization of the security attributes). 32-bit exes made on x86 from the exact code do work when being run on x64. It's hard to sum it up but there is a problem with memory access somewhere. I got back to using the original, padded PureBasic structure because that's how it should be defined. In the end, found out that if I replace AllocateMemory with LocalAlloc_(), the code works with the purifier enabled. Could it be because of this?
Here's a sample:http://msdn.microsoft.com/en-us/library/windows/desktop/aa379561%28v=vs.85%29.aspx wrote:Several functions that use the SECURITY_DESCRIPTOR structure require that this structure be aligned on a valid pointer boundary in memory. These boundaries vary depending on the type of processor used. Memory allocation functions such as malloc and LocalAlloc return properly aligned pointers.
Code: Select all
#SECURITY_DESCRIPTOR_MIN_LENGTH_ = SizeOf(SECURITY_DESCRIPTOR)
Procedure.i CreateMyMutex(Name.s)
Protected Security.SECURITY_ATTRIBUTES
Protected *Descriptor, hMutex.i, Result.i
;With AllocateMemory and Purifier -> error code 998 (invalid memory access)
*Descriptor = AllocateMemory(#SECURITY_DESCRIPTOR_MIN_LENGTH_)
;But this works
;*Descriptor = LocalAlloc_(#LPTR,#SECURITY_DESCRIPTOR_MIN_LENGTH_)
If *Descriptor <> 0
Security\nLength = SizeOf(SECURITY_ATTRIBUTES)
Security\bInheritHandle = #False
Security\lpSecurityDescriptor = *Descriptor
If InitializeSecurityDescriptor_(Security\lpSecurityDescriptor, #SECURITY_DESCRIPTOR_REVISION) <> 0
If SetSecurityDescriptorDacl_(Security\lpSecurityDescriptor, #True, 0, #False) <> 0
hMutex = CreateMutex_(@Security, 0, @Name)
Error = GetLastError_()
Debug "Error: "+Str(Error)
If hMutex <> 0
Result = hMutex
EndIf
EndIf
EndIf
;FreeMemory(*Descriptor)
EndIf
ProcedureReturn Result
EndProcedure
Debug "Result: "+Str(CreateMyMutex("test"))