| Bug # | Delphi versions | Description |
| 141 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
The Inc procedure increments with more than 1. See description under 'documentation' |
| 481 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
If you pass a command line parameter to your program that is longer than 255 characters and then try to read this parameter using the ParamStr function an access violation will occur. |
| 511 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
The Copy function (for dynamic arrays) fails when the passed array is nil |
| 533 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
The Interface-Definition of IShellView.GetItemObject is wrong |
| 193 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
ComObj -
ciInternal COM objects may cause spurious OLE errors |
| 194 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
EditIntf -
Bug in function TIResourceFile.CreateEntry |
| 513 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
IShellBrowser -
The declaration of IShellBrowser.SendControlMsg is wrong. The last parameter should be a pointer to an integer instead of the integer itself |
| 424 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
IniFiles -
In TIniFile.WriteInteger and TIniFile.WriteString, passing a section argument that ends with a space character causes "an invalid page fault in module KRNL386.EXE at 0002:00005c53" |
| 491 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
Internet -
(Win)CGI applications processing a web request return a line like this as part of the result: Status: 200 OK Content-Type: text/html Content-Length: 449 Content: |
| 385 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
Internet -
scktcomp There's a bug in the function TCustomWinSocket.SendStreamPiece in Unit ScktComp.pas. |
| 415 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
JPEG -
TJPEGImage TJPEGImage has a memory leak when 256 colors are used. This bug is caused by a bug in Graphics.pas |
| 195 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
MAPI -
The "GetProcAddress(MAPIModule, 'MapiLogOn')" (and corresponding MapiLogOff function) has the case wrong - it should be MapiLogon (No uppercase O) and MapiLogoff. The function fails until that is changed. |
| 200 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
MMSystem -
The waveInClose function is declared wrong. |
| 201 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
MMSystem -
The declaration for mixerMessage() is missing |
| 196 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
Math -
The function Power gives an error when zero is raised to a power. |
| 197 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
Math -
InternalRateOfReturn function gives incorrect answers |
| 198 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
Math -
There seem to be (many!) more bugs in the financial routines of the MATH unit. Karl Thompson has submitted a message describing bugs in the functions NetPresentValue, DoubleDecliningBalance and FutureValue. I haven't had time yet to verify these bugs, but I trust they are real bugs. I'd be very happy if anyone would take the trouble of checking these bugs and let me (Reinier Sterkenburg) know the results. Any workarounds or pointing at the exact locations where the code is wrong would also be appreciated. |
| 199 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
Math -
Two more functions with bugs: InterestPayment and InterestRate. The latter does work, but the passed parameter values are not adequately explained in the help. |
| 202 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
RichEdit -
TTextRange is declared wrong for TRichEdit |
| 203 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
ShellAPI -
A lot of functions of the SHELL32.DLL are not declared in the Delphi 2 ShellAPI unit. |
| 204 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
ShlObj -
IShellBrowser.SetMenuSB is declared wrong |
| 205 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
ShlObj -
IShellView.GetItemObject is declared wrong |
| 422 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
ShlObj -
The declaration of the HandleMenuMsg function of IContextMenu2 is wrong |
| 216 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
SysUtils -
Val thinks that IntToStr(Low(Integer)) is not a valid integer |
| 217 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
SysUtils -
EncodeDate doesn't add 1900 to the year if the year is < 100 |
| 218 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
SysUtils -
When you call FindClose a second time, the application hangs completely. |
| 219 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
SysUtils -
ShowException() prints a bad address for the exception (console mode apps). This is because it subtracts OFFSET TextStart from the error in an attempt to convert it into a logical address. I think this code came straight out of D1 and just wasn't updated. The result of this error is that you aren't given an address that you can feed into Search|Find Error. |
| 220 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
SysUtils -
StrPCopy only copies first 255 chars |
| 221 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
SysUtils -
StrToDateTime has a bug |
| 222 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
SysUtils -
StrToInt fails on IntToStr(Low(Integer)) See the description under Val (bug # 216) |
| 389 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
SysUtils -
DiskFree and DiskSize report wrong (sometimes negative) values. |
| 507 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
SysUtils -
Using (very) long strings for an Exception message can make the IDE crash. |
| 371 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
SysUtils -
Format Using the FORMAT statement with an integer specifier larger than 15 (ie: '%.16d' ) does not pad with zeros as expected. |
| 206 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
System -
The Round() function can give unexpected results |
| 207 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
System -
ErrorAddr is always NIL in finalization section |
| 208 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
System -
The AssignFile / Reset procedures accept '' (empty string) for a file name and then hang up your system. |
| 209 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
System -
There is an undocumented difference between how Delphi 1's Readln handles error conditions and how Delphi 2 and 3 do this. |
| 210 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
System -
The Reset procedure doesn't work properly on files that are already open. |
| 211 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
System -
There is another bug in the Reset procedure when sharing files. |
| 212 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
System -
The third bug in the Reset procedure is that it fails on files that are Read-only. This is easily worked around by adding the statement FileMode := 0 just before calling Reset. |
| 213 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
System -
Read/Readln fails to read a number from a text file if it has a trailing decimal point. |
| 214 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
System -
Access Violation in procedure SetString for a ShortString when the copy from buffer is empty. |
| 215 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
System -
The Val function fails on strings with spaces at the right |
| 223 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
TLHelp32 -
Wrong length of szModule field of TModuleEntry32 |
| 224 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
TLHelp32 -
Wrong declaration: PModuleEntry32 |
| 232 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
WinSvc -
Declaration of EnumServicesStatus is wrong |
| 225 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
Windows -
BroadcastSystemMessage maps to a wrong function |
| 226 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
Windows -
You can't use the FindFirstChangeNotification as declared in Delphi 3 Windows.pas. |
| 227 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
Windows -
The declaration of TCharInfo is not correct |
| 228 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
Windows -
The declaration of TKeyEventRecord is not correct |
| 230 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
Windows -
You can't pass NIL as the last argument to OffsetWindowOrgEx, while the On-Line help says you can. |
| 231 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
Windows -
Type "TEnumLogFontEx" needed with the EnumFontFamiliesEx API function as defined is hard to use. |
| 391 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
Windows -
The parameter value -1 is specified to give the standard sound but the parameter is declared as a Word and therefore -1 is illegal. |
| 414 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
Windows -
The GetDiskFreeSpaceEx functions are declared with wrong parameter types in the Windows unit. |
| 497 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
Windows -
There is a bug in the WINAPI definition for the function SetWinMetaFileBits |
| 229 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
Windows? -
The routines in both NETAPI and NETAPI32 are uncallable from Delphi. |
| 233 | 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 |
general -
Not bugs but very annoying and sometimes hard to track down, so worth a place in these Bug Lists are the many duplicate names. Some examples are: DeleteFile, FindClose, TBitmap, and there are more. |
Bug #481; last modified: 24-Dec-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Unknown | Exists | Exists | Exists | Exists | Exists | Exists | Exists |
Max Masyutin proposed a fix to the VCL:
Replace the existing GetParamStr function withthe following code:
function GetParamStr(P: PChar; var Param: string): PChar;
function StrLen(Str: PChar): Cardinal; assembler;
asm
MOV EDX,EDI
MOV EDI,EAX
MOV ECX,0FFFFFFFFH
XOR AL,AL
REPNE SCASB
MOV EAX,0FFFFFFFEH
SUB EAX,ECX
MOV EDI,EDX
end;
type
PCharArray = ^TCharArray;
TCharArray = array[0..MaxInt-1] of Char;
var
BufLen, Len: Integer;
Buffer: PCharArray;
begin
BufLen := StrLen(P);
GetMem(Buffer, BufLen);
while True do
begin
while (P[0] <> #0) and (P[0] <= ' ') do Inc(P);
if (P[0] = '"') and (P[1] = '"') then Inc(P, 2) else Break;
end;
Len := 0;
while P[0] > ' ' do
if P[0] = '"' then
begin
Inc(P);
while (P[0] <> #0) and (P[0] <> '"') do
begin
Buffer[Len] := P[0];
Inc(Len);
Inc(P);
end;
if P[0] <> #0 then Inc(P);
end else
begin
Buffer[Len] := P[0];
Inc(Len);
Inc(P);
end;
SetString(Param, Buffer^, Len);
Result := P;
FreeMem(Buffer, BufLen);
end;
Bug #511; last modified: 13-Dec-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | N/A | N/A | N/A | N/A | Gotcha | Gotcha | Gotcha |
A1:= Copy(A2);as a shorthand for this:
A1:= Copy(A2, 0, Length(A2));(where A1, and A2 are dynamic arrays of the same type). Unfortunately, if A2 is nil, the shorthand version will cause an access violation because _DynArrayCopy (in system.pas) forgets to check before dereferencing A2 to get its length.
Bug #533; last modified: 9-Feb-99| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Exists |
function GetItemObject(Item: UINT; const iid: TIID; IPtr: Pointer): HResult; stdcall;Instead it should be:
function GetItemObject(Item: UINT; const iid: TIID; VAR IPtr: Pointer): HResult; stdcall;The Bug leads to crashes when using self-written shell-extensions in the Common-Dialog-Browsers.
IPtr := (pointer to my Interface)but use:
Pointer(IPtr^):= (pointer to my Interface)or correct ShlObj.Pas
Bug #193; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | N/A | Exists | Unknown | Unknown | Unknown | Unknown | Unknown |
TAutoObjectFactory.Create( ComServer,
T_my_COM_object,
{8CC8F401-EA44-11D0-8A63-851049D1071D},
ciInternal);
Now have a look at this code snippet from ComObj.pas, that will be called
as a consequence of the above:
procedure TComObjectFactory.RegisterClassObject;
const
RegFlags: array[ciSingleInstance..ciMultiInstance] of Integer =
(REGCLS_SINGLEUSE, REGCLS_MULTIPLEUSE);
begin
OleCheck(CoRegisterClassObject(FClassID, Self,
CLSCTX_LOCAL_SERVER,
RegFlags[FInstancing], FRegister));
end;
FInstancing will be ciInternal once we come to this routine.
Clearly the access of RegFlags[ciInternal] will return an undefined value; this is best seem by having turned on range checks ($R+) which will automatically give you a range check error.
Can this problem be safely ignored? Probably not, as the OLE documentation make it clear that OLE expects defined parameters to be passed.
{$IFDEF Fix}
if not (FInstancing = ciInternal) then
{$ENDIF}
OleCheck(CoRegisterClassObject(FClassID, Self,
CLSCTX_LOCAL_SERVER,
RegFlags[FInstancing], FRegister));
There appears to be no work-around for this problem.
Bug #194; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown |
Problem example:
var
RF: TIResourceFile;
RE: TIResourceEntry;
...
RE := RF.CreateEntry(PChar(MakeIntResource(rt_Bitmap)),
'MYBITMAP',0,0,0,0,0);
Here, a new bitmap named "MYBITMAP" should be created to the resource file
pointed to by RF. However, no matter what the parameters for CreateEntry
are (valid or not) an Delphi exception occurs. Because of this RE will
always be nil.
Var
RF: TIResourceFile;
RE: TIResourceEntry;
I : Integer;
...
For I := 0 to RF.GetEntryCount-1 do
RE := RF.GetEntry(I); { dummy get to avoid Delphi bug }
RE := RF.CreateEntry(PChar(MakeIntResource(rt_Bitmap)),
'MYBITMAP',0,0,0,0,0);
It might also be enough to get the last entry (RF.GetEntry(RF.GetEntryCount-1)),
but I haven't tested this.
Bug #513; last modified: 20-Dec-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | N/A | Exists | Exists | Exists | Exists | Exists | Exists |
function IShellBrowser.SendControlMsg(ID, Msg: UINT; wParm: WPARAM;
lParm: LPARAM; Result: LResult): HResult; stdcall;
CORRECT:
function IShellBrowser.SendControlMsg(ID, Msg: UINT; wParm: WPARAM;
lParm: LPARAM; Result: PInteger): HResult; stdcall;
var Index : Integer; CurrentShellBrowser.SendControlMsg(FCW_TOOLBAR,TB_COMMANDTOINDEX, Message.ItemID,0,Integer(@Index));note the type cast for the last parameter. BTW: The Windows help file states correctly:
LRESULT *pref // Points to the SendMessage return value
Bug #424; last modified: 16-Jun-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Fixed | Exists | Exists | Exists | Exists | Unknown | Unknown | Unknown |
IniFile := TIniFile.Create('Test.ini');
IniFile.WriteString('Test ', 'Key1', 'Val1');
IniFile.Free;
Note that the last character in the 'Test ' argument on the second line is a
' '. Deleting the ' ' ends the problem.
Interestingly, this problem does not occur in Windows' WritePrivateProfileString. In this API call, the trailing ' ' is simply stripped.
Two other notes:
1. This may be Win95 version dependent. I have not looked into this
thoroughly, but this bug may not occur in some versions of Win95.
2. I've not tested TIniFile.WriteBool for this bug (but I'll bet it's
there)
Notes from checker:
1. I have verified that the bug also occurs with Delphi 2.
2. The bug does not occur under Windows NT 4.0 (SP3).
But the space gets truncated from the section name
Bug #491; last modified: 15-Oct-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | N/A | Exists | Exists | Exists | Exists | Exists | Unknown |
Status: 200 OK Content-Type: text/html Content-Length: 449 Content:
AddHeaderItem(StatusString, 'Status: %s'#13#10);with
AddHeaderItem(StatusString, 'HTTP/1.0 %s'#13#10);2) In TCGIResponse.SendRedirect replace:
HTTPRequest.WriteString(Format('Location: %s', [URI]));
with
HTTPRequest.WriteString(Format('Location: %s'#13#10#13#10, [URI]));
#1 is the solution to your problem. #2 is a fix for another problem
she found (something to do with redirection obviously).
Fix #1 applies to both D3 and D4, but since TCGIResponse.SendRedirect has been rewritten in D4, fix #2 only applies to D3.
Bug #385; last modified: 15-Oct-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Unknown | Unknown | Unknown | Unknown | Exists | Fixed | Fixed | Fixed |
When I encountered these problems, I discovered a bug in the function TCustomWinSocket.SendStreamPiece in unit ScktComp.pas. Look at Line 898.
end else if AmountInBuf > AmountSent then ---> FSendStream.Position := StartPos + (AmountInBuf - AmountSent)Should be replaced by:
end else if AmountInBuf > AmountSent then ---> FSendStream.Position := StartPos + AmountSentI've submitted this bug to Borland Delphi Bug Report it has been confirmed by them.
Bug #200; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Exists | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed |
function waveInClose(hWaveIn: PHWaveIn): Word;
function waveInClose(hWaveIn: HWaveIn): Word;or use your own procedure if you do not like changing the VCL sources:
function CorrectedwaveInClose(hWaveIn: HWaveIn): Word;
external 'MMSYSTEM' index 505;
Bug #201; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Unknown | Exists | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed |
function erMessage(hmx: HMIXER; uMsg: UINT;
dwParam1, dwParam2: DWORD): DWORD; stdcall;
in the implementation:
function erMessage; external mmsyst name 'erMessage';The workaround is to either fix the declaration, or do it in your own unit:
function mixerMessage(hmx: HMIXER; uMsg: UINT;
dwParam1, dwParam2: DWORD): DWORD; stdcall;
function mixerMessage; external mmsyst name 'mixerMessage';
Bug #196; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Exists | Exists | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed |
var x: extended; begin x := Math.Power(0, 0.5); ShowMessage(FloatToStr(x));This raises a "Floating point division by zero" exception.
if Exponent = 0.0 then
Result := 1.0 { By fiat, 0**0 = 1 }
add something like:
Bug #197; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | Exists | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown |
uses
math;
Var
cflow: array[0..8] of double;
irr: double;
begin
cflow[0] := -13560;
cflow[1] := 340;
cflow[2] := 470;
cflow[3] := 611;
cflow[4] := 756;
cflow[5] := 906;
cflow[6] := 1060;
cflow[7] := 1218;
cflow[8] := 26320;
irr := InternalRateofReturn(0.1, cflow);
showmessage(floattostring(irr));
{delphi returns -0.11.. for irr, but the correct irr = 0.12304..}
end;
I submited this bug to Borland.
Bug #199; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | Exists | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown |
Bug #202; last modified: 15-Oct-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | N/A | Exists | Exists | Exists | Fixed | Fixed | Fixed |
TTextRangeA = record
chrg: TCharRange;
lpstrText: PAnsiChar;
end;
TTextRangeW = record
chrg: TCharRange;
lpstrText: PWideChar;
end;
TTextRange = TTextRangeA;
Bug #203; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Unknown | Exists | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed |
const SHARD_PIDL = 1; SHARD_PATH = 2; procedure SHAddToRecentDocs(uFlags: Word; pv: Pointer); stdcall;and in the implementation part:
procedure SHAddToRecentDocs; external 'shell32.dll' name 'SHAddToRecentDocs';Now you can add a file to this menu like this: SHAddToRecentDocs(SHARD_PATH, PChar(Filename));
Bug #204; last modified: 20-Dec-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | N/A | Exists | Exists | Exists | Exists | Exists | Exists |
function SetMenuSB(hMenuShared: HMENU;
hOleMenuReserved: HOLEMENU): HResult; stdcall;
function SetMenuSB(hmenuShared: HMENU;
hOleMenuReserved: HOLEMENU;
HwndActiveObject: Hwnd): HResult; stdcall;
Bug #205; last modified: 15-Oct-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | N/A | Exists | Exists | Exists | Fixed | Fixed | Fixed |
function GetItemObject(Item: UINT; const iid: TIID;
IPtr: Pointer): HResult; stdcall;
Note the added "const" in front of iid.
Bug #422; last modified: 10-Jul-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | Unknown | Exists | Exists | Exists | Fixed | Fixed | Fixed |
function HandleMenuMsg(uMsg: UINT): HResult; stdcall;This is incorrect, it should be:
function HandleMenuMsg(uMsg: UINT; wParam: WPARAM; lParam: LPARAM): HResult; stdcall;This bug has been submitted to Borland. It's reference number is 19050.
type
{ Delphi 3 got the declaration of IContextMenu2 wrong in ShlObj unit. }
IContextMenu2 = interface(IContextMenu)
[SID_IContextMenu2]
function HandleMenuMsg(uMsg: UINT; wParam: WPARAM; lParam: LPARAM):
HResult; stdcall;
end;
Rune Moberg: The bug has been fixed in Delphi 4; the declaration now reads
exactly like Brad's declaration given here.
Bug #216; last modified: 31-Dec-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Absent | Exists | Exists | Exists | Exists | Unknown | Unknown | Fixed |
s := IntToStr(Low(Integer)); i := StrToInt(s);Steve Schafer's answer was:
No, it's not a bug. Most compilers (not just Delphi) parse a string representing a negative integer as a negated positive integer. That is, the compiler sees -12345, so it evaluates 12345, and then negates it. This obviously won't work for the minimum integer, since there is no corresponding positive integer.However I still would say it is a bug. It doesn't help if other compilers have the same bug.
Duncan Murdoch wrote:
The integer value -2147483648 is the smallest legal D2+ integer or D1+
longint. However, the compiler and string conversion routines have
problems with it:
The compiler won't accept
a := -2147483648;presumably because it parses it as a unary minus operator applied to a positive constant. The positive constant is too large, so you get an "Integer constant too large" error. This is irritating, but not a bug.
procedure TForm1.Button1Click(Sender: TObject);
var
a, code: integer; // LongInt doesn't help
s: string;
begin
// This does not compile, though it would be nice if it did
a := -2147483648;
// This will though
a := $80000000;
s := IntToStr(a);
ShowMessage('IntToStr(a) is '+s); // Outputs a is -2147483648
Val(s, a, code);
ShowMessage(Format('Val(s,a,code) gives a=%d and code=%d',[a,code]));
// Right value, but an error is reported
// This will generate an exception
a := StrToInt(s);
end;
function StrToInt(const S: string): Integer;
var
E: Integer;
begin
Val(S, Result, E);
{Bugfix: Start}
// Val reports an error though the value is legal
if (E = 12) and (S = '-2147483648') then exit;
{Bugfix: End}
if E <> 0 then
raise EConvertError.CreateFmt(SInvalidInteger, [S]);
end;
function StrToIntDef(const S: string; Default: Integer): Integer;
var
E: Integer;
begin
Val(S, Result, E);
{Bugfix: Start}
// Val reports an error though the value is legal
if (E = 12) and (S = '-2147483648') then exit;
{Bugfix: End}
if E <> 0 then Result := Default;
end;
Bug #217; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Gotcha | Gotcha | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown |
Bug #218; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Unknown | Unknown | Exists | Unknown | Unknown | Unknown | Unknown | Unknown |
FindClose(SearchRec);
FindClose(SearchRec);
(I have to use Task manager to close it or, if I'm debugging, Ctrl-F2!)
Explanation (by ESJ):
This is not a Delphi bug, but a windows bug. When the invalid handle is
passed to Windows FindClose, FindClose gets some value at a fixed offset
from the handle value, and then starts counting it down
(attempting to validate a handle??). When this fixed value is very large,
the FindClose function might be counting down for a long time, and the app
appears to be locked even though the function will eventually return.
This bug will only be noticed when the value in question is large, which
might be a reason why it hasn't been published earlier.
You can see the value of this variable by entering the following into the
watch window, and set a breakpoint on a call to FindClose (SR)
PDWORD(SR.FindHandle + $14)^
On first call to FindClose, the value is typically below 0x01000000
On second call, the value is often 0xFEEEFEEE on my computer.
Correct behaviour would be for Windows FindClose to determine that the
handle is invalid without the counting down, call
SetLastError(ERROR_INVALID_HANDLE) and return FALSE.
The SysUtils FindClose function should probably raise an exception in
response to the error code.
Sebastian Carvajal added:
In the implementation of FindFirst in SysUtils.pas I found this
line:
if Result <> 0 then FindClose(F);This makes the following example code (also from SysUtils.pas) fail in those cases where FindFirst doesn't return zero:
... FindFirst is typically used in conjunction with
FindNext and FindClose as follows:
Result := FindFirst(Path, Attr, SearchRec);
while Result = 0 do
begin
ProcessSearchRec(SearchRec);
Result := FindNext(SearchRec);
end;
FindClose(SearchRec);
Result := FindFirst(Path, Attr, SearchRec);
If Result = 0 then // <--- this line added!
begin
while Result = 0 do
begin
ProcessSearchRec(SearchRec);
Result := FindNext(SearchRec);
end;
FindClose(SearchRec);
end;
This way FindClose is called only once.
Fix (by Erik Sperling Johansen):
Modify SysUtils.FindClose by inserting this line at the end of the function:
F.FindHandle := INVALID_HANDLE_VALUE;Workaround:
Bug #220; last modified: 15-Oct-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | Exists | Exists | Exists | Exists | Fixed | Fixed | Fixed |
Result := StrLCopy(Dest, PChar(Source), 255);
Additional notes by checker:
This is definitely a bug; the code for StrPCopy has been clearly written
for Delphi 2/3's long-strings since you cannot typecast a short-string
to a PChar. The only explanation I can think of for the "255" value is
that the original coder wanted the "maximum" length of a string, and was
still in a Delphi 1 mindset. In other words, I think s/he intended to write:
Result := StrLCopy(Dest, PChar(Source), High(Integer));
var s: String; c: array[0..4095] of Char; begin StrPCopy( @c[0], s ); // BROKEN StrLCopy( @c[0], PChar(s), Sizeof(c) ); // not broken
Bug #221; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Unknown | Exists | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown |
Bug #389; last modified: 10-Aug-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Exists | Exists | Exists | Exists | Exists | Fixed | Fixed | Fixed |
Note from checker: This works only in the special case that the actual amount is between 2 GB amd 4 GB (or between 6 and 8 etc).
The real solution would be that all these functions will work with 64 bit integers. This has been implemented in Delphi 4.
Bug #507; last modified: 11-Nov-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Unknown | Unknown | Unknown | Unknown | Exists | Exists | Exists | Exists |
procedure TForm1.Button1Click(Sender: TObject);
var longS: string; i: integer;
begin
longS := '';
for i := 1 to 200 do //2k string
longS := longS + '1234567890';
raise Exception.Create(longS);
end;
Cause:
When you look at the code of Exception.Create (unit SysUtils), it turns
out that it uses a local buffer of 1024 bytes to store the message string.
When a longer string is passed, it trashes the stack, which causes
unpredictable errors, among which an immediate shutdown of Delphi
appears to be one of the possibilities.
Bug #371; last modified: 24-Dec-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Exists | Exists | Exists | Exists | Exists | Exists | Exists | Exists |
nTemp:= 3;
sTemp:= Format('%.6d', [nTemp])
{sTemp now equals '000003'}
But, when I tried to do that on a field with 16 digits, it seems to ignore
the specifier. For example:
nTemp:= 3;
sTemp:= Format('%.16d', [nTemp])
{sTemp now equals '3' instead of '0000000000000003'}
This is a bug because the FORMAT specifier '%.16d' should be
padding with zeros. There isn't a documented reason why this
shouldn't work on specifiers larger than 15.
Bug #206; last modified: 10-Aug-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Gotcha | Gotcha | Gotcha | Gotcha | Gotcha | Fixed | Fixed | Fixed |
The 'problem' exists in all versions of Delphi up to Delphi 3.0:
The behaviour of the Round() function has changed between BP 7.0 and
Delphi 1 but Borland hasn't updated the Help/specification
of the function. The problem is with numbers that
have a fractional part of exactly 0.5. According to the On line help:
"The Round function rounds a real-type value to an integer-type value. X is a real-type expression. Round returns a Longint value that is the value of X rounded to the nearest whole number. If X is exactly halfway between two whole numbers, the result is the number with the greatest absolute magnitude."This is not correct. In fact, Round rounds to the nearest even number. Rounding to the nearest even number appears to be known under the name of 'Banker's algorithm' and many people consider this to be the 'proper way' of rounding and therefore think this behaviour is 'as designed'.
Bug #207; last modified: 7-Jan-99| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Absent | Absent | Exists | Unknown | Unknown | Unknown | Unknown | Fixed |
...
RunError(210);
...
finalization
if ErrorAddr <> nil then { has there been a runtime error? }
begin
MessageBox(0, 'Error condition detected', 'Error', mb_ok);
ErrorAddr := nil;
end;
end.
The root of the problem seems to be in SYSTEM.PAS of Delphi 3 which in routine procedure _Halt0; features this code:
if ErrorAddr <> nil then
begin
MakeErrorMessage;
if IsConsole then
WriteLn(PChar(@runErrMsg))
else
MessageBox(0, runErrMsg, errCaption, 0);
ErrorAddr := nil;
end;
procedure TestError; {$IFNDEF Win32} far; {$ENDIF}
begin
if ErrorAddr <> nil then { has there been a runtime error? }
begin
...
end;
initialialization
AddExitProc(TestError);
end.
Bug #208; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Exists | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed |
var
s1, s2: String;
f: TextFile;
begin
s1 := '';
AssignFile(f, s1);
Reset(f);
Readln(f, s2);
{here system hang up completely without any run-time error!!!}
Close(f)
end.
Bug #209; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Gotcha | Gotcha | Gotcha | Gotcha | Gotcha | Gotcha | Gotcha | Gotcha |
program _01read;
uses
sysutils
{$ifdef ver80}
,wincrt
{$endif}
;
var
i,j : integer;
infile : text;
begin
assign(infile,'_01read.dat');
reset(infile);
while not eof(infile) do
begin
{$i-} readln(infile,i,j); {$i+}
if ioresult <> 0 then
writeln('Error reading line')
else
writeln('Read values ',i:3,j:3);
end;
readln;
close(infile);
end.
; 1 1 2 2 3 3 ; 4 4 5 5 6 6
Error reading line Read values 2 2 Read values 3 3 Error reading line Read values 5 5 Read values 6 6
Error reading line Read values 1 1 Read values 2 2 Read values 3 3 Error reading line Read values 4 4 Read values 5 5 Read values 6 6
Bug #210; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Fixed | Exists | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed |
Bug #211; last modified: 29-Oct-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Absent | Exists | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed |
var f1, f2: text;
begin
assign(f1, 'MYFILE');
assign(f2, 'MYFILE');
reset(f1);
reset(f2); {<--- I/O error 32 - sharing violation}
end;
(DM:) I can confirm the bug.
@@calledByReset:
MOV EAX,GENERIC_READ ; open for read
MOV EDX,FILE_SHARE_WRITE ;<--- I THINK, THERE SHOULD BE
FILE_SHARE_READ !!!!
(DM:) I think it should be FILE_SHARE_WRITE+FILE_SHARE_READ, to allow *either*
a read or a write.
Bug #213; last modified: 10-Aug-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Absent | Exists | Unknown | Unknown | Fixed | Fixed | Fixed | Fixed |
10.0 10
10.
Bug #214; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | Exists | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed |
procedure TForm1.Button1StartClick(Sender: TObject); var S : ShortString; //this causes Access Violation // S : AnsiString; //this will *always* work buffer : PChar; begin buffer:= nil; SetString(S, buffer, 10); //Access Violation on ShortString end;
Bug #215; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Gotcha | Gotcha | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown |
Val(' 1.10 ', x, code);
Delphi 1.0 gives: x=0; code=7. (Delphi 2.0 gives a different result,
but also not the result we'd like to see: x=1.1; code=0).
Bug #223; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | Exists | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed |
szModule: array[0..MAX_MODULE_NAME32 + 1] of Char;which makes it MAX_MODULE_NAME32 + 2 characters long.
var p: PChar;
p := ModuleEntry32.szModule;
if p^ = ':' then
Dec (p);
This code will work even when the bug is fixed, because the first character
of "szModule" is supposed to be a drive letter.
Bug #224; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | Exists | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed |
type PModuleEntry32 = ^TProcessEntry32;it should defined as
type PModuleEntry32 = ^TModuleEntry32;
Bug #232; last modified: 28-Jul-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | N/A | Exists | Fixed | Fixed | Fixed | Fixed | Fixed |
function EnumServicesStatusA; external advapi32 name 'EnumServicesStatusA'; function EnumServicesStatusW; external advapi32 name 'EnumServicesStatusW'; function EnumServicesStatus; external advapi32 name 'EnumServicesStatusA';
Bug #225; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Fixed | Fixed | Exists | Unknown | Unknown | Unknown | Unknown | Unknown |
function MyBroadcastSystemMessage(Flags: DWORD; Recipients: PDWORD;
uiMessage: UINT; wParam: WPARAM; lParam: LPARAM): Longint; stdcall;
function MyBroadcastSystemMessage; external user32
name "BroadcastSystemMessage";
Bug #226; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Fixed | Fixed | Gotcha | Unknown | Unknown | Unknown | Unknown | Unknown |
function FindFirstChangeNotification(lpPathName: PChar;
bWatchSubtree: BOOL;
dwNotifyFilter: DWORD): THandle;
stdcall; external kernel32 name 'FindFirstChangeNotificationA';
{$Z4 Must use DWords for this enumeration}
type TWinBool = (winFalse, winTrue);
function _FindFirstChangeNotification(lpPathName: PChar;
bWatchSubtree: TWinBool;
dwNotifyFilter: DWORD): THandle;
stdcall; external kernel32 name 'FindFirstChangeNotificationA';
Bug #227; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | Exists | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed |
typedef struct _CHAR_INFO { // chi
union { /* Unicode or ANSI character */
WCHAR UnicodeChar;
CHAR AsciiChar;
} Char;
WORD Attributes; // text and background colors
} CHAR_INFO, *PCHAR_INFO;
type
PCharInfo = ^TCharInfo;
TCharInfo = packed record
case Integer of
0: (
UnicodeChar: WCHAR);
1: (
AsciiChar: CHAR;
Attributes: Word);
end;
These declaration are not equivalent; in fact sizeof(CHAR_INFO)=4 and sizeof(TCharInfo)=3.
The C version from the help file appears to correct. A better translation
would be:
type
PCharInfo = ^TCharInfo;
TCharInfo = packed record
case Integer of
0: (
UnicodeChar: WCHAR;
Attributes: Word);
1: (
AsciiChar: CHAR);
end;
which lays out the record correctly, and allows proper access to the components.
Bug #228; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | Exists | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed |
Bug #231; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | Exists | Fixed | Fixed | Fixed | Fixed | Fixed | Fixed |
Function MyFontEnumProc(lpelfe: PEnumLogFontEx;
lpntme: PNewTextMetricEx;
FontType: Integer;
LParam: LongInt): LongInt; StdCall;
Begin
TStrings(LParam).Add(lpelfe^.elfFullName); { this line won't compile }
Result := 1; { continue font enumeration }
End;
In this example, the data in "elfFullName" should be added to a string
list (for example, a listbox item list). But because the the field is defined
as an array of bytes, the compiler cannot convert the array correctly to
a (long) string.
Function MyFontEnumProc(lpelfe: PEnumLogFontEx;
lpntme: PNewTextMetricEx;
FontType: Integer;
LParam: LongInt): LongInt; StdCall;
Type
TelfFullName = { define temporary type (see WINDOWS.PAS) }
Array[0..lf_FullFaceSize-1] of Char;
Begin
TStrings(LParam).Add(TelfFullName(lpelfe^.elfFullName)); { do a typecast }
Result := 1; { continue font enumeration }
End;
Solution #2: If you want to avoid this problem in the future and you have
the RTL (VCL) source code, you could modify WINDOWS.PAS directly.
Solution #2 example:
{
Redefine TEnumLogFontEx record to allow quick
conversion of the fields to long strings.
}
PEnumLogFontEx = ^TEnumLogFontEx;
TEnumLogFontEx = packed record
elfLogFont: TLogFont;
elfFullName: array[0..LF_FULLFACESIZE - 1] of char; { modify }
elfStyle: array[0..LF_FACESIZE - 1] of char; { modify }
elfScript: array[0..LF_FACESIZE - 1] of char; { modify }
end;
Bug #391; last modified: 13-Apr-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Exists | Exists | Exists | Exists | Exists | Unknown | Unknown | Unknown |
Bug #414; last modified: 14-May-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | N/A | Exists | Exists | Exists | Fixed | Fixed | Fixed |
function GetDiskFreeSpaceExA(lpDirectoryName: PAnsiChar; var lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes: Integer; lpTotalNumberOfFreeBytes: PInteger): BOOL; stdcall; function GetDiskFreeSpaceExW(lpDirectoryName: PWideChar; var lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes: Integer; lpTotalNumberOfFreeBytes: PInteger): BOOL; stdcall; function GetDiskFreeSpaceEx(lpDirectoryName: PChar; var lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes: Integer; lpTotalNumberOfFreeBytes: PInteger): BOOL; stdcall;The problem with these declaration is that they do not match Microsoft's implementation or documentation of the functions. The last three parameters should be of the type TLargeInteger instead of Integer. Because these parameters are sent by reference and are modified in the functions, calling them with the given declarations can cause access violations. Do _not_ call these functions through the declarations given in the Windows unit.
unit WinFix; interface uses Windows; function GetDiskFreeSpaceExA(lpDirectoryName: PAnsiChar; var lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes: TLargeInteger; lpTotalNumberOfFreeBytes: PLargeInteger): BOOL; stdcall; function GetDiskFreeSpaceExW(lpDirectoryName: PWideChar; var lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes: TLargeInteger; lpTotalNumberOfFreeBytes: PLargeInteger): BOOL; stdcall; function GetDiskFreeSpaceEx(lpDirectoryName: PChar; var lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes: TLargeInteger; lpTotalNumberOfFreeBytes: PLargeInteger): BOOL; stdcall; implementation function GetDiskFreeSpaceExA; external kernel32 name 'GetDiskFreeSpaceExA'; function GetDiskFreeSpaceExW; external kernel32 name 'GetDiskFreeSpaceExW'; function GetDiskFreeSpaceEx; external kernel32 name 'GetDiskFreeSpaceExA'; end.Note that first two parameters are sent as var parameters, while the last is sent as a pointer to TLargeInteger. The reason is that the lpTotalNumberOfFreeBytes parameter can be set to nil if we are not interested in getting the result of it. Also note that these functions are only supported on NT4.0 and Win95 OSR2 and later. See Microsoft's documentation for further details.
To reproduce the bug and test the workaround, use this simple test unit:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
uses
WinFix;
type
TTestDiskFreeRec = record
lpFreeBytesAvailableToCaller,
Safety1,
lpTotalNumberOfBytes,
Safety2,
lpTotalNumberOfFreeBytes,
Safety3 : Integer;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
TestDiskFreeRec: TTestDiskFreeRec;
begin
FillChar(TestDiskFreeRec, SizeOf(TestDiskFreeRec), 255);
with TestDiskFreeRec do
if Windows.GetDiskFreeSpaceEx('D:\', lpFreeBytesAvailableToCaller,
lpTotalNumberOfBytes,
@lpTotalNumberOfFreeBytes) then
begin
// Note that the Safety fields are overwritten!
Writeln('lpFreeBytesAvailableToCaller: ',
lpFreeBytesAvailableToCaller);
Writeln('Safety1: ', Safety1);
Writeln('lpTotalNumberOfBytes: ',
lpTotalNumberOfBytes);
Writeln('Safety2: ', Safety2);
Writeln('lpTotalNumberOfFreeBytes: ',
lpTotalNumberOfFreeBytes);
Writeln('Safety3: ', Safety3);
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
lpFreeBytesAvailableToCaller,
lpTotalNumberOfBytes,
lpTotalNumberOfFreeBytes : TLargeInteger;
begin
if WinFix.GetDiskFreeSpaceEx('D:\', lpFreeBytesAvailableToCaller,
lpTotalNumberOfBytes,
@lpTotalNumberOfFreeBytes) then
begin
Writeln('lpFreeBytesAvailableToCaller: ',
lpFreeBytesAvailableToCaller.QuadPart:0:0);
Writeln('lpTotalNumberOfBytes: ',
lpTotalNumberOfBytes.QuadPart:0:0);
Writeln('lpTotalNumberOfFreeBytes: ',
lpTotalNumberOfFreeBytes.QuadPart:0:0);
end;
end;
end.
Compile as a console application. Pressing button1 shows that the
original declarations in Windows cause memory to be overwritten (the
Safety fields). Pressing button2 demonstrates how to call the correct
versions of the APIs.
Bug #497; last modified: 28-Oct-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Unknown | Exists | Exists | Exists | Exists | Exists | Exists | Exists |
function SetWinMetaFileBits(p1: UINT; p2: PChar; p3: HDC;
const p4: TMetaFilePict): HENHMETAFILE; stdcall;
the fourth parameter 'p4' should be defined as:
const p4: PMetaFilePict
function SetWinMetaFileBits(p1: UINT; p2: PChar; p3: HDC; const p4: PMetaFilePict): HENHMETAFILE; stdcall;in the interface section (before the implementation line, and add:
function SetWinMetaFileBits; external gdi32 name 'SetWinMetaFileBits';to the implementation section, after any uses clause that might be listed.
Bug #229; last modified: before April 1998| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| N/A | Exists | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown |
2: Windows NT Programming
Assuming you get around the loss of all those 16 bit calls, we move
to NT programming where NETAPI32.DLL does have all the calls - yet there
is no entries in WINDOWS.PAS (/BORLAND/Delphi 2.0/Source/RTL/Win) for these
calls.
3: And the loser is ...
Now it has been shown that you can't program 95 or NT NETAPI calls
(need to use Delphi 1.0 - for Windows 95 and write your own interface for
Win/NT) - look for NetRemoteDOT in the help, sure enough it is there..
Bug #233; last modified: 20-Dec-98| 1.02 | 2.01 | 3.0 | 3.01 | 3.02 | 4.0 | 4.01 | 4.02 |
| Gotcha | Gotcha | Gotcha | Gotcha | Gotcha | Gotcha | Gotcha | Gotcha |