2 // purpose: a KOL Registry object that mimics almost exactly VCL registry unit
4 // author: KOL version © 2004, Thaddy de Koning
5 // Portions © 1995-1997 Borland Software Corporation
6 // Based on the Delphi3 professional sourcecode as distributed free with
7 // the Dutch magazine PC-Active in 2000.
9 {.$DEFINE USE_ERR} // If you want true exception handling
12 windows
, messages
,kol
{$IFDEF USE_ERR},err
{$ENDIF};
16 TSysLocale
= packed record
26 MaxSubKeyLen
: Integer;
33 TRegDataType
= (rdUnknown
, rdString
, rdExpandString
, rdInteger
, rdBinary
);
36 RegData
: TRegDataType
;
41 TRegistry
= object(TObj
)
47 FCloseRootKey
: Boolean;
49 procedure SetRootKey(Value
: HKEY
);
51 procedure ChangeKey(Value
: HKey
; const Path
: string);
52 function GetBaseKey(Relative
: Boolean): HKey
;
53 function GetData(const Name
: string; Buffer
: Pointer;
54 BufSize
: Integer; var RegData
: TRegDataType
): Integer;
55 function GetKey(const Key
: string): HKEY
;
56 procedure PutData(const Name
: string; Buffer
: Pointer; BufSize
: Integer; RegData
: TRegDataType
);
57 procedure SetCurrentKey(Value
: HKEY
);
59 destructor Destroy
; virtual;
61 function CreateKey(const Key
: string): Boolean;
62 function DeleteKey(const Key
: string): Boolean;
63 function DeleteValue(const Name
: string): Boolean;
64 function GetDataInfo(const ValueName
: string; var Value
: TRegDataInfo
): Boolean;
65 function GetDataSize(const ValueName
: string): Integer;
66 function GetDataType(const ValueName
: string): TRegDataType
;
67 function GetKeyInfo(var Value
: TRegKeyInfo
): Boolean;
68 procedure GetKeyNames(Strings
: PStrList
);
69 procedure GetValueNames(Strings
: PStrList
);
70 function HasSubKeys
: Boolean;
71 function KeyExists(const Key
: string): Boolean;
72 function LoadKey(const Key
, FileName
: string): Boolean;
73 procedure MoveKey(const OldName
, NewName
: string; Delete
: Boolean);
74 function OpenKey(const Key
: string; CanCreate
: Boolean): Boolean;
75 function OpenKeyReadOnly(const Key
: String): Boolean;
76 function ReadCurrency(const Name
: string): Currency
;
77 function ReadBinaryData(const Name
: string; var Buffer
; BufSize
: Integer): Integer;
78 function ReadBool(const Name
: string): Boolean;
79 function ReadDate(const Name
: string): TDateTime
;
80 function ReadDateTime(const Name
: string): TDateTime
;
81 function ReadFloat(const Name
: string): Double;
82 function ReadInteger(const Name
: string): Integer;
83 function ReadString(const Name
: string): string;
84 function ReadTime(const Name
: string): TDateTime
;
85 function RegistryConnect(const UNCName
: string): Boolean;
86 procedure RenameValue(const OldName
, NewName
: string);
87 function ReplaceKey(const Key
, FileName
, BackUpFileName
: string): Boolean;
88 function RestoreKey(const Key
, FileName
: string): Boolean;
89 function SaveKey(const Key
, FileName
: string): Boolean;
90 function UnLoadKey(const Key
: string): Boolean;
91 function ValueExists(const Name
: string): Boolean;
92 procedure WriteCurrency(const Name
: string; Value
: Currency
);
93 procedure WriteBinaryData(const Name
: string; var Buffer
; BufSize
: Integer);
94 procedure WriteBool(const Name
: string; Value
: Boolean);
95 procedure WriteDate(const Name
: string; Value
: TDateTime
);
96 procedure WriteDateTime(const Name
: string; Value
: TDateTime
);
97 procedure WriteFloat(const Name
: string; Value
: Double);
98 procedure WriteInteger(const Name
: string; Value
: Integer);
99 procedure WriteString(const Name
, Value
: string);
100 procedure WriteExpandString(const Name
, Value
: string);
101 procedure WriteTime(const Name
: string; Value
: TDateTime
);
102 property CurrentKey
: HKEY read FCurrentKey
;
103 property CurrentPath
: string read FCurrentPath
;
104 property LazyWrite
: Boolean read FLazyWrite write FLazyWrite
;
105 property RootKey
: HKEY read FRootKey write SetRootKey
;
106 property Access
: LongWord read FAccess write FAccess
;
109 function NewRegistry
:PRegistry
;overload
;
110 function NewRegistry(AAccess
: LongWord
):Pregistry
;overload
;
111 function Str2IntDef(const S
: string; Default
: Integer): Integer;
114 SysLocale
:TSysLocale
;
115 LeadBytes
: set of Char = [];
119 SInvalidRegType
= 'Invalid data type for ''%s''';
120 SRegCreateFailed
= 'Failed to create key %s';
121 SRegGetDataFailed
= 'Failed to get data for ''%s''';
122 SRegSetDataFailed
= 'Failed to set data for ''%s''';
124 procedure ReadError(const Name
: string);
127 raise Exception
.CreateFmt(e_Custom
,SInvalidRegType
, [Name
]);
129 MsgOk(Format(SInvalidRegType
, [Name
]));
133 function IsRelative(const Value
: string): Boolean;
135 Result
:= not ((Value
<> '') and (Value
[1] = '\'));
138 function RegDataToDataType(Value
: TRegDataType
): Integer;
141 rdString
: Result
:= REG_SZ
;
142 rdExpandString
: Result
:= REG_EXPAND_SZ
;
143 rdInteger
: Result
:= REG_DWORD
;
144 rdBinary
: Result
:= REG_BINARY
;
150 function DataTypeToRegData(Value
: Integer): TRegDataType
;
152 if Value
= REG_SZ
then Result
:= rdString
153 else if Value
= REG_EXPAND_SZ
then Result
:= rdExpandString
154 else if Value
= REG_DWORD
then Result
:= rdInteger
155 else if Value
= REG_BINARY
then Result
:= rdBinary
156 else Result
:= rdUnknown
;
159 function NewRegistry
:PRegistry
;overload
;
164 RootKey
:= HKEY_CURRENT_USER
;
165 FAccess
:= KEY_ALL_ACCESS
;
170 function NewRegistry(AAccess
: LongWord
):Pregistry
;overload
;
173 Result
.FAccess
:= AAccess
;
176 destructor TRegistry
.Destroy
;
182 procedure TRegistry
.CloseKey
;
184 if CurrentKey
<> 0 then
187 RegCloseKey(CurrentKey
) else
188 RegFlushKey(CurrentKey
);
194 procedure TRegistry
.SetRootKey(Value
: HKEY
);
196 if RootKey
<> Value
then
198 if FCloseRootKey
then
200 RegCloseKey(RootKey
);
201 FCloseRootKey
:= False;
208 procedure TRegistry
.ChangeKey(Value
: HKey
; const Path
: string);
211 FCurrentKey
:= Value
;
212 FCurrentPath
:= Path
;
215 function TRegistry
.GetBaseKey(Relative
: Boolean): HKey
;
217 if (CurrentKey
= 0) or not Relative
then
218 Result
:= RootKey
else
219 Result
:= CurrentKey
;
222 procedure TRegistry
.SetCurrentKey(Value
: HKEY
);
224 FCurrentKey
:= Value
;
227 function TRegistry
.CreateKey(const Key
: string): Boolean;
231 Disposition
: Integer;
236 Relative
:= IsRelative(S
);
237 if not Relative
then Delete(S
, 1, 1);
238 Result
:= RegCreateKeyEx(GetBaseKey(Relative
), PChar(S
), 0, nil,
239 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, nil, TempKey
, @Disposition
) = ERROR_SUCCESS
;
240 if Result
then RegCloseKey(TempKey
)
243 raise Exception
.CreateFmt(e_Custom
,SRegCreateFailed
, [Key
]);
245 MsgOk(Format(SRegCreateFailed
, [Key
]));
249 function TRegistry
.OpenKey(const Key
: String; Cancreate
: boolean): Boolean;
253 Disposition
: Integer;
257 Relative
:= IsRelative(S
);
259 if not Relative
then Delete(S
, 1, 1);
261 if not CanCreate
or (S
= '') then
263 Result
:= RegOpenKeyEx(GetBaseKey(Relative
), PChar(S
), 0,
264 FAccess
, TempKey
) = ERROR_SUCCESS
;
266 Result
:= RegCreateKeyEx(GetBaseKey(Relative
), PChar(S
), 0, nil,
267 REG_OPTION_NON_VOLATILE
, FAccess
, nil, TempKey
, @Disposition
) = ERROR_SUCCESS
;
270 if (CurrentKey
<> 0) and Relative
then S
:= CurrentPath
+ '\' + S
;
271 ChangeKey(TempKey
, S
);
275 function TRegistry
.OpenKeyReadOnly(const Key
: String): Boolean;
282 Relative
:= IsRelative(S
);
284 if not Relative
then Delete(S
, 1, 1);
286 Result
:= RegOpenKeyEx(GetBaseKey(Relative
), PChar(S
), 0,
287 KEY_READ
, TempKey
) = ERROR_SUCCESS
;
291 if (CurrentKey
<> 0) and Relative
then S
:= CurrentPath
+ '\' + S
;
292 ChangeKey(TempKey
, S
);
296 Result
:= RegOpenKeyEx(GetBaseKey(Relative
), PChar(S
), 0,
297 STANDARD_RIGHTS_READ
or KEY_QUERY_VALUE
or KEY_ENUMERATE_SUB_KEYS
,
298 TempKey
) = ERROR_SUCCESS
;
301 FAccess
:= STANDARD_RIGHTS_READ
or KEY_QUERY_VALUE
or KEY_ENUMERATE_SUB_KEYS
;
302 if (CurrentKey
<> 0) and Relative
then S
:= CurrentPath
+ '\' + S
;
303 ChangeKey(TempKey
, S
);
307 Result
:= RegOpenKeyEx(GetBaseKey(Relative
), PChar(S
), 0,
308 KEY_QUERY_VALUE
, TempKey
) = ERROR_SUCCESS
;
311 FAccess
:= KEY_QUERY_VALUE
;
312 if (CurrentKey
<> 0) and Relative
then S
:= CurrentPath
+ '\' + S
;
313 ChangeKey(TempKey
, S
);
319 function TRegistry
.DeleteKey(const Key
: string): Boolean;
325 OldKey
, aDeleteKey
: HKEY
;
329 Relative
:= IsRelative(S
);
330 if not Relative
then Delete(S
, 1, 1);
331 OldKey
:= CurrentKey
;
332 aDeleteKey
:= GetKey(Key
);
333 if aDeleteKey
<> 0 then
335 SetCurrentKey(aDeleteKey
);
336 if GetKeyInfo(Info
) then
338 SetString(KeyName
, nil, Info
.MaxSubKeyLen
+ 1);
339 for I
:= Info
.NumSubKeys
- 1 downto 0 do
341 Len
:= Info
.MaxSubKeyLen
+ 1;
342 if RegEnumKeyEx(aDeleteKey
, DWORD(I
), PChar(KeyName
), Len
, nil, nil, nil,
343 nil) = ERROR_SUCCESS
then
344 Self
.DeleteKey(PChar(KeyName
));
348 SetCurrentKey(OldKey
);
349 RegCloseKey(aDeleteKey
);
351 Result
:= RegDeleteKey(GetBaseKey(Relative
), PChar(S
)) = ERROR_SUCCESS
;
354 function TRegistry
.DeleteValue(const Name
: string): Boolean;
356 Result
:= RegDeleteValue(CurrentKey
, PChar(Name
)) = ERROR_SUCCESS
;
359 function TRegistry
.GetKeyInfo(var Value
: TRegKeyInfo
): Boolean;
361 FillChar(Value
, SizeOf(TRegKeyInfo
), 0);
362 Result
:= RegQueryInfoKey(CurrentKey
, nil, nil, nil, @Value
.NumSubKeys
,
363 @Value
.MaxSubKeyLen
, nil, @Value
.NumValues
, @Value
.MaxValueLen
,
364 @Value
.MaxDataLen
, nil, @Value
.FileTime
) = ERROR_SUCCESS
;
365 if SysLocale
.FarEast
and (WinVer
>= WvNT
) then
368 Inc(MaxSubKeyLen
, MaxSubKeyLen
);
369 Inc(MaxValueLen
, MaxValueLen
);
373 procedure TRegistry
.GetKeyNames(Strings
: PStrList
);
381 if GetKeyInfo(Info
) then
383 SetString(S
, nil, Info
.MaxSubKeyLen
+ 1);
384 for I
:= 0 to Info
.NumSubKeys
- 1 do
386 Len
:= Info
.MaxSubKeyLen
+ 1;
387 RegEnumKeyEx(CurrentKey
, I
, PChar(S
), Len
, nil, nil, nil, nil);
388 Strings
.Add(PChar(S
));
393 procedure TRegistry
.GetValueNames(Strings
: PStrList
);
401 if GetKeyInfo(Info
) then
403 SetString(S
, nil, Info
.MaxValueLen
+ 1);
404 for I
:= 0 to Info
.NumValues
- 1 do
406 Len
:= Info
.MaxValueLen
+ 1;
407 RegEnumValue(CurrentKey
, I
, PChar(S
), Len
, nil, nil, nil, nil);
408 Strings
.Add(PChar(S
));
413 function TRegistry
.GetDataInfo(const ValueName
: string; var Value
: TRegDataInfo
): Boolean;
417 FillChar(Value
, SizeOf(TRegDataInfo
), 0);
418 Result
:= RegQueryValueEx(CurrentKey
, PChar(ValueName
), nil, @DataType
, nil,
419 @Value
.DataSize
) = ERROR_SUCCESS
;
420 Value
.RegData
:= DataTypeToRegData(DataType
);
423 function TRegistry
.GetDataSize(const ValueName
: string): Integer;
427 if GetDataInfo(ValueName
, Info
) then
428 Result
:= Info
.DataSize
else
432 function TRegistry
.GetDataType(const ValueName
: string): TRegDataType
;
436 if GetDataInfo(ValueName
, Info
) then
437 Result
:= Info
.RegData
else
441 procedure TRegistry
.WriteString(const Name
, Value
: string);
443 PutData(Name
, PChar(Value
), Length(Value
)+1, rdString
);
446 procedure TRegistry
.WriteExpandString(const Name
, Value
: string);
448 PutData(Name
, PChar(Value
), Length(Value
)+1, rdExpandString
);
451 function TRegistry
.ReadString(const Name
: string): string;
454 RegData
: TRegDataType
;
456 Len
:= GetDataSize(Name
);
459 SetString(Result
, nil, Len
);
460 GetData(Name
, PChar(Result
), Len
, RegData
);
461 if (RegData
= rdString
) or (RegData
= rdExpandString
) then
462 SetLength(Result
, StrLen(PChar(Result
)))
463 else ReadError(Name
);
468 procedure TRegistry
.WriteInteger(const Name
: string; Value
: Integer);
470 PutData(Name
, @Value
, SizeOf(Integer), rdInteger
);
473 function TRegistry
.ReadInteger(const Name
: string): Integer;
475 RegData
: TRegDataType
;
477 GetData(Name
, @Result
, SizeOf(Integer), RegData
);
478 if RegData
<> rdInteger
then ReadError(Name
);
481 procedure TRegistry
.WriteBool(const Name
: string; Value
: Boolean);
483 WriteInteger(Name
, Ord(Value
));
486 function TRegistry
.ReadBool(const Name
: string): Boolean;
488 Result
:= ReadInteger(Name
) <> 0;
491 procedure TRegistry
.WriteFloat(const Name
: string; Value
: Double);
493 PutData(Name
, @Value
, SizeOf(Double), rdBinary
);
496 function TRegistry
.ReadFloat(const Name
: string): Double;
499 RegData
: TRegDataType
;
501 Len
:= GetData(Name
, @Result
, SizeOf(Double), RegData
);
502 if (RegData
<> rdBinary
) or (Len
<> SizeOf(Double)) then
506 procedure TRegistry
.WriteCurrency(const Name
: string; Value
: Currency
);
508 PutData(Name
, @Value
, SizeOf(Currency
), rdBinary
);
511 function TRegistry
.ReadCurrency(const Name
: string): Currency
;
514 RegData
: TRegDataType
;
516 Len
:= GetData(Name
, @Result
, SizeOf(Currency
), RegData
);
517 if (RegData
<> rdBinary
) or (Len
<> SizeOf(Currency
)) then
521 procedure TRegistry
.WriteDateTime(const Name
: string; Value
: TDateTime
);
523 PutData(Name
, @Value
, SizeOf(TDateTime
), rdBinary
);
526 function TRegistry
.ReadDateTime(const Name
: string): TDateTime
;
529 RegData
: TRegDataType
;
531 Len
:= GetData(Name
, @Result
, SizeOf(TDateTime
), RegData
);
532 if (RegData
<> rdBinary
) or (Len
<> SizeOf(TDateTime
)) then
536 procedure TRegistry
.WriteDate(const Name
: string; Value
: TDateTime
);
538 WriteDateTime(Name
, Value
);
541 function TRegistry
.ReadDate(const Name
: string): TDateTime
;
543 Result
:= ReadDateTime(Name
);
546 procedure TRegistry
.WriteTime(const Name
: string; Value
: TDateTime
);
548 WriteDateTime(Name
, Value
);
551 function TRegistry
.ReadTime(const Name
: string): TDateTime
;
553 Result
:= ReadDateTime(Name
);
556 procedure TRegistry
.WriteBinaryData(const Name
: string; var Buffer
; BufSize
: Integer);
558 PutData(Name
, @Buffer
, BufSize
, rdBinary
);
561 function TRegistry
.ReadBinaryData(const Name
: string; var Buffer
; BufSize
: Integer): Integer;
563 RegData
: TRegDataType
;
566 if GetDataInfo(Name
, Info
) then
568 Result
:= Info
.DataSize
;
569 RegData
:= Info
.RegData
;
570 if ((RegData
= rdBinary
) or (RegData
= rdUnknown
)) and (Result
<= BufSize
) then
571 GetData(Name
, @Buffer
, Result
, RegData
)
572 else ReadError(Name
);
577 procedure TRegistry
.PutData(const Name
: string; Buffer
: Pointer;
578 BufSize
: Integer; RegData
: TRegDataType
);
582 DataType
:= RegDataToDataType(RegData
);
583 if RegSetValueEx(CurrentKey
, PChar(Name
), 0, DataType
, Buffer
,
584 BufSize
) <> ERROR_SUCCESS
then
586 raise Exception
.CreateFmt(e_Custom
,SRegSetDataFailed
, [Name
]);
588 MsgOk(Format(SRegSetDataFailed
, [Name
]));
592 function TRegistry
.GetData(const Name
: string; Buffer
: Pointer;
593 BufSize
: Integer; var RegData
: TRegDataType
): Integer;
597 DataType
:= REG_NONE
;
598 if RegQueryValueEx(CurrentKey
, PChar(Name
), nil, @DataType
, PByte(Buffer
),
599 @BufSize
) <> ERROR_SUCCESS
then
601 raise Exception
.CreateFmt(e_Custom
,SRegGetDataFailed
, [Name
]);
605 MsgOk(Format(SRegGetDataFailed
, [Name
]));
609 RegData
:= DataTypeToRegData(DataType
);
612 function TRegistry
.HasSubKeys
: Boolean;
616 Result
:= GetKeyInfo(Info
) and (Info
.NumSubKeys
> 0);
619 function TRegistry
.ValueExists(const Name
: string): Boolean;
623 Result
:= GetDataInfo(Name
, Info
);
626 function TRegistry
.GetKey(const Key
: string): HKEY
;
632 Relative
:= IsRelative(S
);
633 if not Relative
then Delete(S
, 1, 1);
635 RegOpenKeyEx(GetBaseKey(Relative
), PChar(S
), 0, FAccess
, Result
);
638 function TRegistry
.RegistryConnect(const UNCName
: string): Boolean;
642 Result
:= RegConnectRegistry(PChar(UNCname
), RootKey
, TempKey
) = ERROR_SUCCESS
;
646 FCloseRootKey
:= True;
650 function TRegistry
.LoadKey(const Key
, FileName
: string): Boolean;
655 if not IsRelative(S
) then Delete(S
, 1, 1);
656 Result
:= RegLoadKey(RootKey
, PChar(S
), PChar(FileName
)) = ERROR_SUCCESS
;
659 function TRegistry
.UnLoadKey(const Key
: string): Boolean;
664 if not IsRelative(S
) then Delete(S
, 1, 1);
665 Result
:= RegUnLoadKey(RootKey
, PChar(S
)) = ERROR_SUCCESS
;
668 function TRegistry
.RestoreKey(const Key
, FileName
: string): Boolean;
673 aRestoreKey
:= GetKey(Key
);
674 if aRestoreKey
<> 0 then
676 Result
:= RegRestoreKey(aRestoreKey
, PChar(FileName
), 0) = ERROR_SUCCESS
;
678 RegCloseKey(aRestoreKey
);
682 function TRegistry
.ReplaceKey(const Key
, FileName
, BackUpFileName
: string): Boolean;
688 Relative
:= IsRelative(S
);
689 if not Relative
then Delete(S
, 1, 1);
690 Result
:= RegReplaceKey(GetBaseKey(Relative
), PChar(S
),
691 PChar(FileName
), PChar(BackUpFileName
)) = ERROR_SUCCESS
;
694 function TRegistry
.SaveKey(const Key
, FileName
: string): Boolean;
699 aSaveKey
:= GetKey(Key
);
700 if aSaveKey
<> 0 then
702 Result
:= RegSaveKey(aSaveKey
, PChar(FileName
), nil) = ERROR_SUCCESS
;
704 RegCloseKey(aSaveKey
);
708 function TRegistry
.KeyExists(const Key
: string): Boolean;
713 OldAccess
:= FAccess
;
715 FAccess
:= STANDARD_RIGHTS_READ
or KEY_QUERY_VALUE
or KEY_ENUMERATE_SUB_KEYS
;
716 TempKey
:= GetKey(Key
);
717 if TempKey
<> 0 then RegCloseKey(TempKey
);
718 Result
:= TempKey
<> 0;
720 FAccess
:= OldAccess
;
724 procedure TRegistry
.RenameValue(const OldName
, NewName
: string);
727 RegData
: TRegDataType
;
730 if ValueExists(OldName
) and not ValueExists(NewName
) then
732 Len
:= GetDataSize(OldName
);
735 Buffer
:= AllocMem(Len
);
737 Len
:= GetData(OldName
, Buffer
, Len
, RegData
);
738 DeleteValue(OldName
);
739 PutData(NewName
, Buffer
, Len
, RegData
);
747 procedure TRegistry
.MoveKey(const OldName
, NewName
: string; Delete
: Boolean);
749 SrcKey
, DestKey
: HKEY
;
751 procedure MoveValue(SrcKey
, DestKey
: HKEY
; const Name
: string);
754 OldKey
, PrevKey
: HKEY
;
756 RegData
: TRegDataType
;
758 OldKey
:= CurrentKey
;
759 SetCurrentKey(SrcKey
);
761 Len
:= GetDataSize(Name
);
764 Buffer
:= AllocMem(Len
);
766 Len
:= GetData(Name
, Buffer
, Len
, RegData
);
767 PrevKey
:= CurrentKey
;
768 SetCurrentKey(DestKey
);
770 PutData(Name
, Buffer
, Len
, RegData
);
772 SetCurrentKey(PrevKey
);
779 SetCurrentKey(OldKey
);
783 procedure CopyValues(SrcKey
, DestKey
: HKEY
);
787 KeyInfo
: TRegKeyInfo
;
791 OldKey
:= CurrentKey
;
792 SetCurrentKey(SrcKey
);
794 if GetKeyInfo(KeyInfo
) then
796 MoveValue(SrcKey
, DestKey
, '');
797 SetString(S
, nil, KeyInfo
.MaxValueLen
+ 1);
798 for I
:= 0 to KeyInfo
.NumValues
- 1 do
800 Len
:= KeyInfo
.MaxValueLen
+ 1;
801 if RegEnumValue(SrcKey
, I
, PChar(S
), Len
, nil, nil, nil, nil) = ERROR_SUCCESS
then
802 MoveValue(SrcKey
, DestKey
, PChar(S
));
806 SetCurrentKey(OldKey
);
810 procedure CopyKeys(SrcKey
, DestKey
: HKEY
);
816 OldKey
, PrevKey
, NewSrc
, NewDest
: HKEY
;
818 OldKey
:= CurrentKey
;
819 SetCurrentKey(SrcKey
);
821 if GetKeyInfo(Info
) then
823 SetString(S
, nil, Info
.MaxSubKeyLen
+ 1);
824 for I
:= 0 to Info
.NumSubKeys
- 1 do
826 Len
:= Info
.MaxSubKeyLen
+ 1;
827 if RegEnumKeyEx(SrcKey
, I
, PChar(S
), Len
, nil, nil, nil, nil) = ERROR_SUCCESS
then
829 NewSrc
:= GetKey(PChar(S
));
832 PrevKey
:= CurrentKey
;
833 SetCurrentKey(DestKey
);
836 NewDest
:= GetKey(PChar(S
));
838 CopyValues(NewSrc
, NewDest
);
839 CopyKeys(NewSrc
, NewDest
);
841 RegCloseKey(NewDest
);
844 SetCurrentKey(PrevKey
);
853 SetCurrentKey(OldKey
);
858 if KeyExists(OldName
) and not KeyExists(NewName
) then
860 SrcKey
:= GetKey(OldName
);
864 DestKey
:= GetKey(NewName
);
867 CopyValues(SrcKey
, DestKey
);
868 CopyKeys(SrcKey
, DestKey
);
869 if Delete
then DeleteKey(OldName
);
871 RegCloseKey(DestKey
);
879 function Str2IntDef(const S
: string; Default
: Integer): Integer;
884 if E
<> 0 then Result
:= Default
;
887 function LCID2CodePage(ALcid
: LCID
): Integer;
889 Buffer
: array [0..6] of Char;
891 GetLocaleInfo(ALcid
, LOCALE_IDEFAULTANSICODEPAGE
, Buffer
, SizeOf(Buffer
));
892 Result
:= Str2IntDef(Buffer
, GetACP
);
895 procedure InitSysLocale
;
898 DefaultLangID
: LANGID
;
901 BufferA
: array [128..255] of Char;
902 BufferW
: array [128..256] of Word;
905 procedure InitLeadBytes
;
910 GetCPInfo(LCID2CodePage(SysLocale
.DefaultLCID
), AnsiCPInfo
);
914 while (I
< MAX_LEADBYTES
) and ((LeadByte
[I
] or LeadByte
[I
+ 1]) <> 0) do
916 for J
:= LeadByte
[I
] to LeadByte
[I
+ 1] do
917 Include(LeadBytes
, Char(J
));
923 function IsWesternGroup
: Boolean;
925 TLangGroup
= $00..$1D;
926 TLangGroups
= set of TLangGroup
;
928 lgNeutral
= TLangGroup($00);
929 lgDanish
= TLangGroup($06);
930 lgDutch
= TLangGroup($13);
931 lgEnglish
= TLangGroup($09);
932 lgFinnish
= TLangGroup($0B);
933 lgFrench
= TLangGroup($0C);
934 lgGerman
= TLangGroup($07);
935 lgItalian
= TLangGroup($10);
936 lgNorwegian
= TLangGroup($14);
937 lgPortuguese
= TLangGroup($16);
938 lgSpanish
= TLangGroup($0A);
939 lgSwedish
= TLangGroup($1D);
941 WesternGroups
: TLangGroups
= [
956 Result
:= SysLocale
.PriLangID
in WesternGroups
;
960 { Set default to English (US). }
961 SysLocale
.DefaultLCID
:= $0409;
962 SysLocale
.PriLangID
:= LANG_ENGLISH
;
963 SysLocale
.SubLangID
:= SUBLANG_ENGLISH_US
;
965 DefaultLCID
:= GetThreadLocale
;
966 if DefaultLCID
<> 0 then SysLocale
.DefaultLCID
:= DefaultLCID
;
968 DefaultLangID
:= Word(DefaultLCID
);
969 if DefaultLangID
<> 0 then
971 SysLocale
.PriLangID
:= DefaultLangID
and $3ff;
972 SysLocale
.SubLangID
:= DefaultLangID
shr 10;
976 if WinVer
>= wvNT
then
978 if IsWesternGroup
then
980 SysLocale
.MiddleEast
:= False;
981 SysLocale
.FarEast
:= False;
985 { Far East (aka MBCS)? - }
987 SysLocale
.FarEast
:= LeadBytes
<> [];
988 if SysLocale
.FarEast
then
990 SysLocale
.MiddleEast
:= False;
995 for I
:= Low(BufferA
) to High(BufferA
) do
996 BufferA
[I
] := Char(I
);
997 PCharA
:= @BufferA
; { not null terminated: include length in GetStringTypeExA call }
998 GetStringTypeEx(SysLocale
.DefaultLCID
, CT_CTYPE2
, PCharA
, High(BufferA
) - Low(BufferA
) + 1, BufferW
);
999 for I
:= Low(BufferA
) to High(BufferA
) do
1001 SysLocale
.MiddleEast
:= BufferW
[I
] = C2_RIGHTTOLEFT
;
1002 if SysLocale
.MiddleEast
then
1009 SysLocale
.MiddleEast
:= GetSystemMetrics(SM_MIDEASTENABLED
) <> 0;
1010 SysLocale
.FarEast
:= GetSystemMetrics(SM_DBCSENABLED
) <> 0;
1011 if SysLocale
.FarEast
then