Warning! Windows Server DLL Issue
- RichAlgeni
- Addict
- Posts: 935
- Joined: Wed Sep 22, 2010 1:50 am
- Location: Bradenton, FL
Warning! Windows Server DLL Issue
This is an issue that seems to have arisen since the beginning of the year in both Windows Server 2008 and 2012.
I do not believe it is a bug, I believe it is a change Microsoft has made. It has to do with using a list, map or dimensioned array at the beginning of a dll, which is NOT inside a procedure. I have for a number of years now utilizing PureBasic includes for both mainline routines and dlls. Since I have used them, they have worked fine. Until last Thursday!
While troubleshooting a server database access issue, and not having much success, I installed Windows updates for a Windows Server 2008 machine. Updates had not been installed since just after Christmas. It turns out that the database access issue was not on the server, but a bad odbc driver on a client machine. Anyway, after the server was rebooted, a number of my programs had crashed. It took a number of hours to pin the problems down to my dll's. After a number of hours testing and troubleshooting this weekend, I found the issue. Any dll's of mine called by any mainline routine was crashing, including IIS, Internet Information Server. After creating a barebones calling process, and my main include process to load various variables and constants I use. After 59 attempts of removing various pieces of code (I used the compile count), I found the problem. I used a list process to add included programs to the list of programs the dll was compiled with. The dll crashed the mainline routine when the mainline routine tried to load it.
I tested with a list, a map and dimensioned array. All crashed the mainline routine. When I changed this code to simply append the program name to the program list. The mainline routine no longer crashed. I tested the same scenario on a Windows 2012r2 machine that had also not loaded updates since just after Christmas, and had no problems. Once updates were loaded, the mainline processes also crashed when attempting to open a dll that included a AddElement() statement.
As far as I can tell, nothing else changed on these two machines, other than Windows updates. I have several versions of PureBasic loaded on my development machine, and was able to test back to version 5.21, from 5.42. The different versions made no difference!
I do not believe it is a bug, I believe it is a change Microsoft has made. It has to do with using a list, map or dimensioned array at the beginning of a dll, which is NOT inside a procedure. I have for a number of years now utilizing PureBasic includes for both mainline routines and dlls. Since I have used them, they have worked fine. Until last Thursday!
While troubleshooting a server database access issue, and not having much success, I installed Windows updates for a Windows Server 2008 machine. Updates had not been installed since just after Christmas. It turns out that the database access issue was not on the server, but a bad odbc driver on a client machine. Anyway, after the server was rebooted, a number of my programs had crashed. It took a number of hours to pin the problems down to my dll's. After a number of hours testing and troubleshooting this weekend, I found the issue. Any dll's of mine called by any mainline routine was crashing, including IIS, Internet Information Server. After creating a barebones calling process, and my main include process to load various variables and constants I use. After 59 attempts of removing various pieces of code (I used the compile count), I found the problem. I used a list process to add included programs to the list of programs the dll was compiled with. The dll crashed the mainline routine when the mainline routine tried to load it.
I tested with a list, a map and dimensioned array. All crashed the mainline routine. When I changed this code to simply append the program name to the program list. The mainline routine no longer crashed. I tested the same scenario on a Windows 2012r2 machine that had also not loaded updates since just after Christmas, and had no problems. Once updates were loaded, the mainline processes also crashed when attempting to open a dll that included a AddElement() statement.
As far as I can tell, nothing else changed on these two machines, other than Windows updates. I have several versions of PureBasic loaded on my development machine, and was able to test back to version 5.21, from 5.42. The different versions made no difference!
- RichAlgeni
- Addict
- Posts: 935
- Joined: Wed Sep 22, 2010 1:50 am
- Location: Bradenton, FL
Re: Warning! Windows Server DLL Issue
Here is the dll I used to test, simply comment out lines 10 and 11, recompile and test again.
And here is the calling parent process:
Please note that I have not yet updated my Windows 7 development machine. I prefer to do a full backup before loading windows updates.
Code: Select all
; ------------------------------------------------------------
; Program name: test_call_dll.pb
; Purpose: 64 bit dll to test a calling problem!
; ------------------------------------------------------------
EnableExplicit
Global NewList programList.s()
AddElement(programList())
programList() = "test_call_dll.pb"
; ************************************************************************************
; dll initialization procedure
; ************************************************************************************
ProcedureDLL.i AttachProcess(instance.i)
EndProcedure
; ************************************************************************************
; dll detach process
; ************************************************************************************
ProcedureDLL.i DetachProcess(instance.i)
EndProcedure
; ************************************************************************************
; dll attach thread
; ************************************************************************************
ProcedureDLL.i AttachThread(instance.i)
EndProcedure
; ************************************************************************************
; dll detach thread
; ************************************************************************************
ProcedureDLL.i DetachThread(instance.i)
EndProcedure
; ************************************************************************************
; test procedure called inside the dll
; ************************************************************************************
ProcedureDLL.i test_dll_procedure(instance.i)
ProcedureReturn #PB_Editor_CompileCount
EndProcedure
; IDE Options = PureBasic 5.42 LTS (Windows - x64)
; ExecutableFormat = Shared dll
; CursorPosition = 9
; EnableThread
; Executable = test_call_dll.dll
; DisableDebugger
; HideErrorLog
; CurrentDirectory = D:\dev\PureBasic\temp\
; CompileSourceDirectory
; Compiler = PureBasic 5.42 LTS (Windows - x64)
; EnableCompileCount = 11
; EnableBuildCount = 11
; EnableExeConstant
; IncludeVersionInfo
; VersionField15 = VOS_NT
; VersionField16 = VFT_DLL
Code: Select all
; ------------------------------------------------------------
; Program name: test01.pb
; Purpose: 64 bit exe to test a dll calling problem!
; ------------------------------------------------------------
EnableExplicit
Define result.i
Define cplibLibrary.i
Define libraryName.s
Define someNumber.i = #PB_Editor_CompileCount
Global NewList programList.s()
AddElement(programList())
programList() = "test01.pb"
OpenConsole()
libraryName = "test_call_dll.dll"
PrintN("filesize of " + libraryName + " is: " + Str(FileSize(libraryName)))
cplibLibrary = OpenLibrary(#PB_Any, libraryName)
If cplibLibrary <= 0
PrintN("!!!!!!!! Unable to open library: " + libraryName + " !!!!!!!!")
PrintN("cplibLibrary = " + Str(cplibLibrary))
Else
; prototype the procedure in the dll
Prototype test_dll_procedure(someNumber.i)
Define test_dll_procedure.test_dll_procedure = GetFunction(cplibLibrary, "test_dll_procedure")
; now call the dll procedure
result = test_dll_procedure(someNumber)
PrintN("test_dll_procedure returned result = " + Str(result))
EndIf
CloseConsole()
End
; IDE Options = PureBasic 5.42 LTS (Windows - x64)
; ExecutableFormat = Console
; CursorPosition = 12
; Executable = test01.exe
; CurrentDirectory = D:\dev\PureBasic\temp\
; CompileSourceDirectory
; EnableCompileCount = 9
; EnableBuildCount = 9
; EnableExeConstant
Re: Warning! Windows Server DLL Issue
I remember some note from PB docs
Don't know why it has to be done this way (can someone explain?), in my DLLs I ignored this (also even not declaring all those AttachProcess ()
) and they working fine anyway. But maybe in your case it matters.
Also your examples seems working fine.
Code: Select all
- The declaration of arrays, lists or map with Dim, NewList or NewMap must always be done inside the procedure AttachProcess.

Also your examples seems working fine.
Last edited by Lunasole on Mon Mar 07, 2016 3:58 pm, edited 3 times in total.
"W̷i̷s̷h̷i̷n̷g o̷n a s̷t̷a̷r"
Re: Warning! Windows Server DLL Issue
Help and my PB DLL Notes wrote: ; All arrays, linked-lists or maps with Dim, NewList or NewMap must be done in Procedure AttachProcess()!
; No program code outside Procedures, except declaration of variables or structures.
; DirectX initialization routines cannot be written in Procedure AttachProcess().
; Only Global strings can be returned from the DLL.
; Not sure where DataSections are handled, but no crashes so far.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
- RichAlgeni
- Addict
- Posts: 935
- Joined: Wed Sep 22, 2010 1:50 am
- Location: Bradenton, FL
Re: Warning! Windows Server DLL Issue
It used to work on Windows!
The issue I am having is that I wanted to use the same include for mainline routines and dll's, for consistency purposes. I used the list to keep track of programs included into the parent process, along with their version numbers. I then can write out that list inside an onerror clause if needed.
I am able to append a string, but I wonder how much longer that will last?
The issue I am having is that I wanted to use the same include for mainline routines and dll's, for consistency purposes. I used the list to keep track of programs included into the parent process, along with their version numbers. I then can write out that list inside an onerror clause if needed.
I am able to append a string, but I wonder how much longer that will last?
Re: Warning! Windows Server DLL Issue
I use:
CompilerIf #ThisIsDLL
AttachProcess()
CompilerElse
ThisLib_AttachProcess()
CompilerEndIf
CompilerIf #ThisIsDLL
AttachProcess()
CompilerElse
ThisLib_AttachProcess()
CompilerEndIf
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
- RichAlgeni
- Addict
- Posts: 935
- Joined: Wed Sep 22, 2010 1:50 am
- Location: Bradenton, FL
Re: Warning! Windows Server DLL Issue
Great idea!skywalk wrote:I use:
CompilerIf #ThisIsDLL
AttachProcess()
CompilerElse
ThisLib_AttachProcess()
CompilerEndIf
I had implemented an initialize process in most of my includes, so I think I will just place the code in there, and not have to worry about it.
Re: Warning! Windows Server DLL Issue
Until the same nightmare as RichAlgeni had it.Lunasole wrote:I remember some note from PB docsDon't know why it has to be done this way (can someone explain?), in my DLLs I ignored this (also even not declaring all those AttachProcess ()Code: Select all
- The declaration of arrays, lists or map with Dim, NewList or NewMap must always be done inside the procedure AttachProcess.
) and they working fine anyway. But maybe in your case it matters.
Also your examples seems working fine.

DLLs are just libraries with only procedures. So code outside of a procedure is forbidden.
Complexe datastructures like array, map or linked list need a little bit more to set up.
If it works now, you will just have a fun time ahead of you.

Thats why AttachProcess() is the way to go as already stated.

MFG PMV
- RichAlgeni
- Addict
- Posts: 935
- Joined: Wed Sep 22, 2010 1:50 am
- Location: Bradenton, FL
Re: Warning! Windows Server DLL Issue
Agreed 100% MFG PMV! I have now created an initialization procedure for all of my PureBasic include type program, and have just completed adding a call to each initialization procedure into AttachProcess().PMV wrote:Thats why AttachProcess() is the way to go as already stated.![]()
It was stupid of me to blindly assume that AddElecment() would work there!
Re: Warning! Windows Server DLL Issue
Well I'm using map in one dll declared this way;PMV wrote: Until the same nightmare as RichAlgeni had it.![]()
DLLs are just libraries with only procedures. So code outside of a procedure is forbidden.
Complexe datastructures like array, map or linked list need a little bit more to set up.
If it works now, you will just have a fun time ahead of you.
Thats why AttachProcess() is the way to go as already stated.![]()
MFG PMV
Code: Select all
Global NewMap TMap.TRecord()
So until I got some "fun time" I won't do any extra movement anyway, hah.
"W̷i̷s̷h̷i̷n̷g o̷n a s̷t̷a̷r"
- RichAlgeni
- Addict
- Posts: 935
- Joined: Wed Sep 22, 2010 1:50 am
- Location: Bradenton, FL
Re: Warning! Windows Server DLL Issue
Declaring the variable is fine. My issue was that I was using AddElement(), but not in a procedure. That was the statement that was creating the fatal error condition.