ndkutils.pas 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. {
  2. FPC Utility Functions for Native NT applications
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 2009 by Sven Barth
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$IFNDEF FPC_DOTTEDUNITS}
  12. unit NDKUtils;
  13. {$ENDIF FPC_DOTTEDUNITS}
  14. {$mode objfpc}{$H+}
  15. interface
  16. {$IFDEF FPC_DOTTEDUNITS}
  17. uses
  18. NTApi.NDK;
  19. {$ELSE FPC_DOTTEDUNITS}
  20. uses
  21. NDK;
  22. {$ENDIF FPC_DOTTEDUNITS}
  23. // Helpers for converting Pascal string types to NT's UNICODE_STRING
  24. procedure ShortStrToNTStr(aStr: ShortString; var aNTStr: UNICODE_STRING);
  25. procedure AnsiStrToNTStr(const aStr: RawByteString; var aNTStr: UNICODE_STRING);
  26. procedure UnicodeStrToNtStr(const aStr: UnicodeString;
  27. var aNTStr: UNICODE_STRING);
  28. procedure PCharToNTStr(aStr: PAnsiChar; aLen: Cardinal; var aNTStr: UNICODE_STRING);
  29. procedure FreeNTStr(var aNTStr: UNICODE_STRING);
  30. // Wraps NtDisplayString for use with Write(Ln)
  31. procedure AssignDisplayString(var aFile: Text; aUtf8: Boolean);
  32. implementation
  33. {$IFDEF FPC_DOTTEDUNITS}
  34. uses
  35. System.SysUtils;
  36. {$ELSE FPC_DOTTEDUNITS}
  37. uses
  38. SysUtils;
  39. {$ENDIF FPC_DOTTEDUNITS}
  40. procedure ShortStrToNTStr(aStr: ShortString; var aNTStr: UNICODE_STRING);
  41. var
  42. buf: Pointer;
  43. i: Integer;
  44. begin
  45. aNTStr.Length := Length(aStr) * 2;
  46. aNTStr.buffer := GetMem(aNTStr.Length);
  47. buf := aNTStr.buffer;
  48. for i := 1 to Length(aStr) do begin
  49. PWord(buf)^ := Word(aStr[i]);
  50. buf := Pointer(PtrUInt(buf) + SizeOf(Word));
  51. end;
  52. aNTStr.MaximumLength := aNTStr.Length;
  53. end;
  54. procedure AnsiStrToNTStr(const aStr: RawByteString; var aNTStr: UNICODE_STRING);
  55. var
  56. buf: PWideChar;
  57. i: Integer;
  58. begin
  59. aNTStr.Length := Length(aStr) * 2;
  60. aNTStr.Buffer := GetMem(aNTStr.Length);
  61. buf := aNTStr.buffer;
  62. for i := 1 to Length(aStr) do begin
  63. buf^ := WideChar(Word(aStr[i]));
  64. Inc(buf);
  65. end;
  66. aNTStr.MaximumLength := aNTStr.Length;
  67. end;
  68. procedure UnicodeStrToNtStr(const aStr: UnicodeString;
  69. var aNTStr: UNICODE_STRING);
  70. var
  71. buf: PWideChar;
  72. begin
  73. { TODO : check why this prints garbage }
  74. aNTStr.Length := Length(aStr) * 2;
  75. aNTStr.Buffer := GetMem(aNTStr.Length);
  76. if Length(aStr) > 0 then
  77. Move(aStr[1], aNTStr.Buffer^, aNTStr.Length);
  78. aNTStr.MaximumLength := aNTStr.Length;
  79. end;
  80. procedure PCharToNTStr(aStr: PAnsiChar; aLen: Cardinal; var aNTStr: UNICODE_STRING);
  81. var
  82. i: Integer;
  83. begin
  84. if (aLen = 0) and (aStr <> Nil) and (aStr^ <> #0) then
  85. aLen := StrLen(aStr);
  86. aNtStr.Length := aLen * SizeOf(WideChar);
  87. aNtStr.MaximumLength := aNtStr.Length;
  88. aNtStr.Buffer := GetMem(aNtStr.Length);
  89. for i := 0 to aLen do
  90. aNtStr.Buffer[i] := aStr[i];
  91. end;
  92. procedure FreeNTStr(var aNTStr: UNICODE_STRING);
  93. begin
  94. if aNTStr.Buffer <> Nil then
  95. FreeMem(aNTStr.Buffer);
  96. FillChar(aNTStr, SizeOf(UNICODE_STRING), 0);
  97. end;
  98. function DisplayStringWriteFunc(var aFile: TTextRec ): LongInt;
  99. var
  100. ntstr: TNtUnicodeString;
  101. len: SizeUInt;
  102. begin
  103. Result := 0;
  104. with aFile do
  105. if (BufPos>0) then begin
  106. if Boolean(UserData[1]) then begin
  107. { TODO : check why UTF8 prints garbage }
  108. {len := Utf8ToUnicode(Nil, 0, PAnsiChar(BufPtr), BufPos);
  109. ntstr.Length := len * 2;
  110. ntstr.MaximumLength := ntstr.Length;
  111. ntstr.Buffer := GetMem(ntstr.Length);
  112. Utf8ToUnicode(ntstr.Buffer, len, PAnsiChar(BufPtr), BufPos);}
  113. PCharToNtStr(PAnsiChar(BufPtr), BufPos, ntstr);
  114. end else
  115. PCharToNtStr(PAnsiChar(BufPtr), BufPos, ntstr);
  116. NtDisplayString(@ntstr);
  117. // FreeNTStr uses FreeMem, so we don't need an If here
  118. FreeNtStr(ntstr);
  119. BufPos := 0;
  120. end;
  121. end;
  122. function DisplayStringCloseFunc(var aFile: TTextRec): LongInt;
  123. begin
  124. Result := 0;
  125. end;
  126. function DisplayStringOpenFunc(var aFile: TTextRec ): LongInt;
  127. begin
  128. Result := 0;
  129. end;
  130. procedure AssignDisplayString(var aFile: Text; aUtf8: Boolean);
  131. begin
  132. FillChar(aFile, SizeOf(TextRec), 0);
  133. { only set things that are not zero }
  134. TextRec(aFile).Handle := UnusedHandle;
  135. TextRec(aFile).mode := fmOutput;
  136. TextRec(aFile).BufSize := TextRecBufSize;
  137. TextRec(aFile).Bufptr := @TextRec(aFile).Buffer;
  138. TextRec(aFile).OpenFunc := @DisplayStringOpenFunc;
  139. case DefaultTextLineBreakStyle of
  140. tlbsLF:
  141. TextRec(aFile).LineEnd := #10;
  142. tlbsCRLF:
  143. TextRec(aFile).LineEnd := #13#10;
  144. tlbsCR:
  145. TextRec(aFile).LineEnd := #13;
  146. end;
  147. TextRec(aFile).Closefunc := @DisplayStringCloseFunc;
  148. TextRec(aFile).InOutFunc := @DisplayStringWriteFunc;
  149. TextRec(aFile).FlushFunc := @DisplayStringWriteFunc;
  150. TextRec(aFile).UserData[1] := Ord(aUTF8);
  151. end;
  152. end.