Delphi2010/CB2010的一个BUG.在Win2K SP4之前的系统上会出问题.
解决代码是:
1 unit D2009Win2kFix; 2 3 { 4 Inno Setup 5 Copyright (C) 1997-2010 Jordan Russell 6 Portions by Martijn Laan 7 For conditions of distribution and use, see LICENSE.TXT. 8 9 When Windows 2000 with SP<4 is detected, this unit reverts the change in 10 Delphi 2009 Update 3 that causes VCL apps (even new, empty projects) to 11 crash on startup when run on Windows 2000 with no SP/SP1/SP2/sometimes SP3. 12 13 This should be at the top of the .dpr's "uses" clause to ensure it runs 14 before any VCL code. 15 16 $jrsoftware: issrc/Projects/D2009Win2kFix.pas,v 1.1 2010/03/03 18:50:21 jr Exp $ 17 } 18 19 interface 20 21 implementation 22 23 {$IFDEF VER200} 24 {$DEFINE Delphi2009Or2010} 25 {$ENDIF} 26 {$IFDEF VER210} 27 {$DEFINE Delphi2009Or2010} 28 {$ENDIF} 29 30 {$IFDEF Delphi2009Or2010} { Only Delphi 2009/2010 } 31 uses 32 Windows, SysUtils; 33 34 { 35 Details: 36 In Delphi 2009 Update 3 (or possibly one of the previous updates), 37 TUTF8Encoding.Create in SysUtils was changed to set the 38 MB_ERR_INVALID_CHARS flag: 39 40 original: inherited Create(CP_UTF8); 41 with Update 3: inherited Create(CP_UTF8, MB_ERR_INVALID_CHARS, 0); 42 43 It appears that when used with CP_UTF8, the MB_ERR_INVALID_CHARS flag is 44 only supported beginning with Windows 2000 SP4 and Windows XP. On Windows 45 2000 with no SP, MultiByteToWideChar() fails with ERROR_INVALID_FLAGS. 46 47 In Delphi 2010 Update 1 this change is still present. 48 49 This code changes TEncoding.UTF8's private FMBToWCharFlags field from 50 MB_ERR_INVALID_CHARS back to 0 when Windows 2000 (5.0) with SP<4 is 51 detected. 52 53 Note: This won't fix any other instances of TUTF8Encoding, but there 54 shouldn't be more than just the one. (Inside the Delphi RTL/VCL, 55 TEncoding.GetUTF8 is the only place where TUTF8Encoding.Create is called.) 56 } 57 58 function NeedWin2kFix: Boolean; 59 var 60 Info: TOSVersionInfoEx; 61 begin 62 Result := False; 63 Info.dwOSVersionInfoSize := SizeOf(Info); 64 if GetVersionEx(Info) then 65 if (Info.dwMajorVersion = 5) and (Info.dwMinorVersion = 0) and 66 (Info.wServicePackMajor < 4) then 67 Result := True; 68 end; 69 70 procedure ApplyWin2kFix; 71 type 72 PLongWordArray = ^TLongWordArray; 73 TLongWordArray = array[0..6] of LongWord; { 28 bytes } 74 var 75 U: SysUtils.TEncoding; 76 begin 77 U := SysUtils.TEncoding.UTF8; 78 if (U.ClassType = SysUtils.TUTF8Encoding) and 79 (U.InstanceSize = 28) and 80 (U is SysUtils.TMBCSEncoding) and 81 (SysUtils.TMBCSEncoding.InstanceSize = 28) then begin 82 if (PLongWordArray(U)[3] = 65001) and { verify that FCodePage = CP_UTF8 } 83 (PLongWordArray(U)[4] = 8) and { verify that FMBToWCharFlags = MB_ERR_INVALID_CHARS } 84 (PLongWordArray(U)[5] = 0) then { verify that FWCharToMBFlags = 0 } 85 PLongWordArray(U)[4] := 0; { change FMBToWCharFlags to 0 } 86 end; 87 end; 88 89 initialization 90 if NeedWin2kFix then 91 ApplyWin2kFix; 92 {$ENDIF} 93 end.
转成C代码
1 void ApplyWin2kFix() 2 { 3 OSVERSIONINFOEX osvi; 4 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); 5 GetVersionEx((LPOSVERSIONINFO) & osvi); 6 7 //Win2000 -- Win2KSP3 8 if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 && osvi.wServicePackMajor < 4) 9 { 10 TEncoding * u = Sysutils::TEncoding::UTF8; 11 if (u->ClassName() == "TUTF8Encoding" && u->InstanceSize() == 28) 12 { 13 DWORD *p = (DWORD*)u; 14 if (p[3] == CP_UTF8 && p[4] == MB_ERR_INVALID_CHARS && p[5] == 0) 15 p[4] = 0; 16 } 17 } 18 } 19 //在工程中, 把 ApplyWin2kFix(); 加在 Application->Initialize();之前