[fpc-pascal] Problem compiling DLL for 64Bit Windows - complete example attached
Lukas Gradl
fpc at ssn.at
Thu Dec 17 20:40:24 CET 2009
Hi!
I'm having serious troubles compiling a DLL for 64bit Windows.
I'm using FPC svn 14444 (Ver 2.5.1) on all machines. I tried on WinXP
32bit (works), Vista 64bit (doesn't work), Win7 32Bit (works) and Win7
64bit (doesn't work).
The DLL works as a print-monitor, providing a virtual printer port.
For the definitions I used the windows-Unit whereever it would work, the
missing ones (mainly the Monitor-Structure i ported from MSDN.
(http://msdn.microsoft.com/en-us/library/aa506794.aspx)
To see the problem copy the resulting dll in your \windows\system32
folder. Then add a registry folder
HKLM\SYSTEM\CurrentControlSet\Control\Print\Monitors\PMon64Test
Inside this folder add a string named "Driver" with a value of
"PMon64.dll" (which has to be the name of the dll in the System32 Folder.
Restart the Spooler-Service and try to add a Printer to your system.
On Win64 the Spooler Service will produce an Error with the ErrorCode
0x000006be, on win32 the normal AddPrinter Dialog will appear.
The source attached provides a basic dll, wich will do nothing but write
some information to C:\TMP\DEBUG.TXT if that file is existant (so please
create it first!)
The Source is:
------------Start
library PMon64;
{$mode Delphi}
{$H+}
uses Windows, Sysutils;
type
pMonitor=^rMonitor;
TEnumPortsFunc=function(pName:LPWSTR;dwLevel:DWORD;pPorts:LPBYTE;
cbBuf:DWORD;pdwNeeded:LPDWORD;
pdwReturned:LPDWORD):BOOL;stdcall;
TOpenPortFunc=function(pName:LPWSTR;H:PHANDLE):BOOL;stdcall;
TOpenPortExFunc=function(pName,pPrinterName:LPWSTR;H:PHANDLE;
_Monitor:pMonitor):BOOL;stdcall;
TStartDocPortFunc=function(hPort:HANDLE;pPrinterName:LPWSTR;
JobID,Level:DWORD;
pDocInfo:LPBYTE):BOOL;stdcall;
TWritePortFunc=function(hPort:HANDLE;pBuffer:LPBYTE;
cbBuf:DWORD;pcbWritten:LPDWORD):BOOL;stdcall;
TReadPortFunc=function(hPort:HANDLE;pBuffer:LPBYTE;cbBuf:DWORD;
pcbRead:LPDWORD):BOOL;stdcall;
TEndDocPortFunc=function(hPort:HANDLE):BOOL;stdcall;
TClosePortFunc=function(hPort:HANDLE):BOOL;stdcall;
TAddPortFunc=function(pName:LPWSTR;h:HWND;
pMonitorName:LPWSTR):BOOL;stdcall;
TAddPortExFunc=function(pName:LPWSTR;Level:DWORD;pBuffer:LPBYTE;
pMonitorName:LPWSTR):BOOL;stdcall;
TConfigurePortFunc=function(pName:LPWSTR;h:HWND;
pMonitorName:LPWSTR):BOOL;stdcall;
TDeletePortFunc=function(pName:LPWSTR;h:HWND;
pMonitorName:LPWSTR):BOOL;stdcall;
TGetPrinterDataFromPortFunc=function(hPort:HANDLE;ControlID:DWORD;
pValueName,lpInBuffer:LPWSTR;
cbInBuffer:DWORD;
lpOutBuffer:LPWSTR;
cbOutBuffer:DWORD;
lpcbReturned:LPDWORD):BOOL;stdcall;
TSetPortTimeOutsFunc=function(hPort:HANDLE;lpTCO:pCommTimeouts;
reserved:DWORD):BOOL;stdcall;
TXcvOpenPortFunc=function(pszObject:LPCWSTR;GrantedAccess:ACCESS_MASK;
phXcv:PHANDLE):BOOL;stdcall;
TXcvDataPortFunc=function(hXcv:HANDLE;pszDataName:LPCWSTR;
pInputData:PBYTE;cbInputData:DWORD;
pOutputData:PBYTE;cbOutputData:DWORD;
pcbOutputNeeded:PDWORD):DWORD;stdcall;
TXcvClosePortFunc=function(hXcv:HANDLE):BOOL;stdcall;
rMonitor=packed record
pfnEnumPorts: TEnumPortsFunc;
pfnOpenPort: TOpenPortFunc;
pfnOpenPortEx: TOpenPortExFunc;
pfnStartDocPort: TStartDocPortFunc;
pfnWritePort: TWritePortFunc;
pfnReadPort: TReadPortFunc;
pfnEndDocPort: TEndDocPortFunc;
pfnClosePort: TClosePortFunc;
pfnAddPort: TAddPortFunc;
pfnAddPortEx: TAddPortExFunc;
pfnConfigurePort: TConfigurePortFunc;
pfnDeletePort: TDeletePortFunc;
pfnGetPrinterDataFromPort: TGetPrinterDataFromPortFunc;
pfnSetPortTimeOuts: TSetPortTimeOutsFunc;
pfnXcvOpenPort: TXcvOpenPortFunc;
pfnXcvDataPort: TXcvDataPortFunc;
pfnXcvClosePort: TXcvClosePortFunc;
end;
rMonitorEx=packed record
dwMonitorSize:DWORD;
Monitor:rMonitor;
end;
pMonitorEx=^rMonitorEx;
var
Mon:rMonitorEx;
procedure DbgSend(Text:String);
var f:Textfile;
begin
if FileExists('C:\TMP\DEBUG.TXT') then begin
AssignFile(f,'C:\TMP\DEBUG.TXT');
Append(f);
Writeln(f,FormatDateTime('HH:MM:SS',now())+': '+Trim(Text));
CloseFile(f);
end;
end;
function EnumPorts(pName:LPWSTR;dwLevel:DWORD;pPorts:LPBYTE;
cbBuf:DWORD;pdwNeeded:LPDWORD;
pdwReturned:LPDWORD):BOOL;stdcall;
begin
DbgSend('EnumPorts');
end;
function OpenPort(pName:LPWSTR;H:PHANDLE):BOOL;stdcall;
begin
DbgSend('OpenPort');
end;
function StartDocPort(hPort:HANDLE;pPrinterName:LPWSTR;
JobID,Level:DWORD;pDocInfo:LPBYTE):BOOL;stdcall;
begin
DbgSend('StartDocPort');
end;
function WritePort(hPort:HANDLE;pBuffer:LPBYTE;cbBuf:DWORD;
pcbWritten:LPDWORD):BOOL;stdcall;
begin
DbgSend('WritePort');
end;
function ReadPort(hPort:HANDLE;pBuffer:LPBYTE;cbBuf:DWORD;
pcbRead:LPDWORD):BOOL;stdcall;
begin
DbgSend('ReadPort');
end;
function EndDocPort(hPort:HANDLE):BOOL;stdcall;
begin
DbgSend('EndDocPort');
end;
function ClosePort(hPort:HANDLE):BOOL;stdcall;
begin
DbgSend('ClosePort');
end;
function AddPort(pName:LPWSTR;h:HWND;pMonitorName:LPWSTR):BOOL;stdcall;
begin
DbgSend('AddPort');
end;
function AddPortEx(pName:LPWSTR;Level:DWORD;pBuffer:LPBYTE;
pMonitorName:LPWSTR):BOOL;stdcall;
begin
DbgSend('AddPortEx');
end;
function ConfigurePort(pName:LPWSTR;h:HWND;
pMonitorName:LPWSTR):BOOL;stdcall;
begin
DbgSend('ConfigurePort');
end;
function DeletePort(pName:LPWSTR;h:HWND;
pMonitorName:LPWSTR):BOOL;stdcall;
begin
DbgSend('DeletePort');
end;
function InitializePrintMonitor(pRegRoot:LPWSTR):pMonitorEx;stdcall;export;
begin
DbgSend('InitializePrintMonitor start');
Result:=@Mon;
DbgSend('InitializePrintMonitor end');
end;
exports InitializePrintMonitor;
begin
DbgSend('MainSection start');
Mon.dwMonitorSize:=SizeOf(rMonitor);
Mon.Monitor.pfnEnumPorts:=EnumPorts;
Mon.Monitor.pfnOpenPort:=OpenPort;
Mon.Monitor.pfnOpenPortEx:=nil;
Mon.Monitor.pfnStartDocPort:=StartDocPort;
Mon.Monitor.pfnWritePort:=WritePort;
Mon.Monitor.pfnReadPort:=ReadPort;
Mon.Monitor.pfnEndDocPort:=EndDocPort;
Mon.Monitor.pfnClosePort:=ClosePort;
Mon.Monitor.pfnAddPort:=AddPort;
Mon.Monitor.pfnAddPortEx:=AddPortEx;
Mon.Monitor.pfnConfigurePort:=ConfigurePort;
Mon.Monitor.pfnDeletePort:=DeletePort;
Mon.Monitor.pfnGetPrinterDataFromPort:=nil;
Mon.Monitor.pfnSetPortTimeOuts:=nil;
Mon.Monitor.pfnXcvOpenPort:=nil;
Mon.Monitor.pfnXcvDataPort:=nil;
Mon.Monitor.pfnXcvClosePort:=nil;
DbgSend('MainSection end');
end.
------------End
I compiled it by the command
32Bit:
fpc -WB0 -MDelphi -B -O- -Os -CX -g- -XDs -Pi386 -TWin32 -vewi PMon64.lpr
and 64Bit.
fpc -WB0 -MDelphi -B -O- -Os -CX -g- -XDs -Px86_64 -TWin64 -vewi PMon64.lpr
The debug.txt on 32 Bit reads:
20:11:37: MainSection start
20:11:37: MainSection end
20:11:37: InitializePrintMonitor start
20:11:37: InitializePrintMonitor end
20:11:37: EnumPorts
The debug.txt on 64 Bit reads:
20:11:37: MainSection start
20:11:37: MainSection end
20:11:37: InitializePrintMonitor start
20:11:37: InitializePrintMonitor end
--> The EnumPorts-Entry is missing here!
so the crash is before or on calling the EnumPorts-Function.
So, anyone an Idea what I might have missed? Or is ther a bug in FPC for
Win64?
Any help would be appreciated.
Regards
Lukas
--
--------------------------
software security networks
Lukas Gradl <fpc#ssn.at>
Eduard-Bodem-Gasse 5
A - 6020 Innsbruck
Tel: +43-512-214040-0
Fax: +43-512-214040-21
--------------------------
More information about the fpc-pascal
mailing list