tw35060a.pp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. { %TARGET=win32,win64,wince }
  2. program tw35060a;
  3. {$apptype console}
  4. {$assertions on}
  5. {$ifdef fpc}
  6. {$codepage cp1252}
  7. {$mode objfpc}
  8. {$h+}
  9. {$endif fpc}
  10. uses
  11. SysUtils, Classes, Windows, Registry;
  12. {$ifndef fpc}
  13. type
  14. UnicodeString = WideString;
  15. function GetLastOSError: Integer;
  16. begin
  17. Result := GetLastError;
  18. end;
  19. {$endif}
  20. const
  21. ExpectedAnsiHex = 'E4 EB EF';
  22. ExpectedUnicodeHex = '00E4 00EB 00EF';
  23. BugID = 'FPCBug0035060';
  24. function UnicodeToHex(const S: UnicodeString): String;
  25. var
  26. i: Integer;
  27. begin
  28. Result := '';
  29. for i := 1 to length(S) do
  30. Result := Result + IntToHex(Word(S[i]),4) + #32;
  31. Result := Trim(Result);
  32. end;
  33. function AnsiToHex(const S: String): String;
  34. var
  35. i: Integer;
  36. begin
  37. Result := '';
  38. for i := 1 to length(S) do
  39. Result := Result + IntToHex(Byte(S[i]),2) + #32;
  40. Result := Trim(Result);
  41. end;
  42. procedure CreateKeyInHKCU(const Key: UnicodeString);
  43. Var
  44. u: UnicodeString;
  45. Disposition: Dword;
  46. Handle: HKEY;
  47. SecurityAttributes: Pointer; //LPSECURITY_ATTRIBUTES;
  48. FLastError: LongInt;
  49. begin
  50. SecurityAttributes := Nil;
  51. u:=Key;
  52. Handle := 0;
  53. FLastError:=RegCreateKeyExW(HKEY_CURRENT_USER,
  54. PWideChar(u),
  55. 0,
  56. '',
  57. REG_OPTION_NON_VOLATILE,
  58. KEY_ALL_ACCESS,
  59. SecurityAttributes,
  60. Handle,
  61. @Disposition);
  62. RegCloseKey(Handle);
  63. Assert(FLastError=ERROR_SUCCESS,format('Creating key "%s" using plain Windows API failed: "%s"',
  64. [String(Key),Trim(SysErrorMessage(FLastError))]));
  65. end;
  66. procedure CreateTestKey;
  67. const
  68. TestKey: UnicodeString = 'Software\'+ UniCodeString(BugID)+ '\äëï';
  69. var
  70. Len: Integer;
  71. begin
  72. Len := Length(TestKey);
  73. //Being a bit paranoid here?
  74. Assert((Len=26) and (Word(TestKey[Len])=$EF) and (Word(TestKey[Len-1])=$EB) and (Word(TestKey[Len-2])=$E4),'Wrong encoding of TestKey');
  75. CreateKeyInHKCU(TestKey);
  76. end;
  77. procedure RemoveTestKey;
  78. const
  79. TestKeyFull: UnicodeString = 'Software\'+ UniCodeString(BugID)+ '\äëï';
  80. TestKeyBugID: UnicodeString = 'Software\'+ UniCodeString(BugID);
  81. var
  82. Key: UnicodeString;
  83. FLastError: LongInt;
  84. begin
  85. Key:=TestKeyFull;
  86. FLastError:=RegDeleteKeyW(HKEY_CURRENT_USER,PWideChar(Key));
  87. Assert(FLastError=ERROR_SUCCESS,format('Removing key "%s" using plain Windows API failed: "%s"',
  88. [String(Key),Trim(SysErrorMessage(FLastError))]));
  89. Key:=TestKeyBugID;
  90. FLastError:=RegDeleteKeyW(HKEY_CURRENT_USER,PWideChar(Key));
  91. Assert(FLastError=ERROR_SUCCESS,format('Removing key "%s" using plain Windows API failed: "%s"',
  92. [String(Key),Trim(SysErrorMessage(FLastError))]));
  93. end;
  94. //End Registry plain API functions
  95. var
  96. R: TRegistry;
  97. Name, S, Key: String;
  98. U: UnicodeString;
  99. B: Boolean;
  100. Err: Integer;
  101. CP: TSystemCodePage;
  102. begin
  103. CreateTestKey;
  104. try
  105. Name := 'äëï';
  106. U := UnicodeString(Name);
  107. S := AnsiToHex(Name);
  108. Assert(S=ExpectedAnsiHex,format('Name is wrongly encoded: expected: %s, found: %s',[ExpectedAnsiHex,S]));
  109. S := UnicodeToHex(U);
  110. Assert(S=ExpectedUnicodeHex,format('Name is wrongly encoded: expected: %s, found: %s',[ExpectedUnicodeHex,S]));
  111. R := TRegistry.Create(KEY_ALL_ACCESS);
  112. try
  113. R.RootKey := HKEY_CURRENT_USER;
  114. Key := '\Software\'+BugId+'\'+Name;
  115. CP := System.StringCodePage(Key);
  116. Assert(CP <> 65001,format('The string that contains the key does not have CP_ACP as dynamic code page, but has codepage %d',[CP]));
  117. B := R.OpenKeyReadOnly(Key);
  118. Err := GetLastOSError;
  119. Assert(B,format('OpenKey(''%s'') failed: "%s" [%d]',[Key,Trim(SysErrorMessage(Err)),Err]));
  120. writeln(format('OpenKeyReadOnly(''%s''): OK',[Key]));
  121. finally
  122. R.Free;
  123. end;
  124. finally
  125. RemoveTestKey;
  126. end;
  127. end.