Windows 7 欢迎界面(将 C# 翻译为 Pascal)

3

Jon在下面的帖子中提供的代码似乎恰好说明了我想做的事情。

在Windows 7欢迎屏幕上运行进程

不幸的是,它是用C#编写的,这是我完全不懂的语言。我正在尝试将代码翻译成Pascal(在Windows 7上使用最新版本的Lazarus)。通过阅读代码之间的空白,我认为我可能已经理解了很多 - 但是,只有当它不能完成任务时,我才会知道是否出错。目前,在以下位置它无法编译。

if (!DuplicateTokenEx(userToken, 0x10000000, ref tokenAttributes,   
SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenImpersonation,
out newToken)) {
log("ERROR: DuplicateTokenEx returned false - "

我的Pascal版本:

If Not DuplicateTokenEx(UserToken, MAXIMUM_ALLOWED, tokenAttributes,
SecurityImpersonation, TokenPrimary, newToken) then
  Writeln(DLog, 'Failed to duplicate security token'); 

在六个参数中的第五个参数上,Lazarus会抛出一个错误。

dmain.pas(189,110) 错误:第5个参数类型不兼容:得到“TOKEN_TYPE”,期望“_TOKEN_TYPE”-这表明我没有理解参数的作用。(将参数5更改为TokenImpersonation会导致相同的错误。)

往下看,我变得更加迷失:

tokPrivs.Privileges = new LUID_AND_ATTRIBUTES[1];
tokPrivs.Privileges[0].Luid = seDebugNameValue;
tokPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

我看到 Windows API 中有结构类型 LUID_AND_ATTRIBUTES,但似乎 Lazarus 不识别它。
简而言之,我在摸索中。我尝试过搜索“C# for Pascal programmers”,但没有找到任何有用的信息。学习 C# 不是一件轻松的事情,因此我会非常感激有关它与 Object Pascal 之间差异以及如何翻译此代码的任何提示。
编辑:根据要求未完成的代码。
function RunOurProcess(ProgramName: String): Boolean;
var
StartInfo: TStartupInfo;
ProcInfo: TProcessInformation;
NewToken, Token, UserToken: THandle;
WPID: DWord;
ThreadAttributes, TokenAttributes: TSecurityAttributes;
TOKPrivs: TTokenPrivileges;
begin
    FillChar(StartInfo, SizeOf(TStartupInfo), #0);
    FillChar(ProcInfo, SizeOf(TProcessInformation), #0);
    StartInfo.cb:= SizeOf(TStartupInfo);
    { Insert handle of current desktop - without this, GUI app is not visible!
      To appear before logon, lpDesktop value should be 'winsta0\WinLogon' }
    StartInfo.lpDesktop:= PChar('winsta0\WinLogon');
    // Save the process ID of the WinLogon process
    WPID:= FindInProcesses('Winlogon.exe');
    // Get the handle of this
    Token:= OpenProcess(TOKEN_QUERY or TOKEN_IMPERSONATE or TOKEN_DUPLICATE, False, WPID);
    // Open a process token using the handle above
    If OpenProcessToken(Token, TOKEN_QUERY or TOKEN_IMPERSONATE or TOKEN_DUPLICATE, UserToken) then
    Writeln(DLog, 'Opened process token for WinLogon')
        else
    Writeln(DLog, 'Failed to open process token for WinLogon');
    // Create a new token
    NewToken:= 0;
    tokenAttributes.nLength:= SizeOf(tokenAttributes);
    threadAttributes.nLength:= SizeOf(threadAttributes);
    If Not DuplicateTokenEx(UserToken, MAXIMUM_ALLOWED, tokenAttributes, SecurityImpersonation, TokenImpersonation, newToken) then
    Writeln(DLog, 'Failed to duplicate security token');
    // Elevate the privileges of the token
    AdjustTokenPrivileges(NewToken, False, {NewState, BufferLength, PreviousState, ReturnLength});
    // LogOnUser
    // If successful, CreateProcessAsUser
    // In progress - code below needs to go before 'CreateProcessAsUser'
    StartInfo.cb:= SizeOf(TStartupInfo);
    // Insert handle of current desktop - without this, GUI app is not visible!
    StartInfo.lpDesktop:= PChar('winsta0\WinLogon');
end; // RunOurProcess            

我注意到,如果我尝试查找“DuplicateTokenEx”的声明,我会收到以下错误:

C:\lazarus\fpc\2.6.1\source\packages\winunits-jedi\src\jwawindows.pas(366,5) 错误: 找不到包含文件“JwaLmErr.pp”


你还没有告诉我们你正在使用的任何类型。另外,你从哪里获取 DuplicateTokenEx?请提供一个完整的程序。 - David Heffernan
感谢您的回复,David。我正在尝试发布我的完整单元,但唯一可见的选项是“添加评论”,页面告诉我这太长了,超过8000个字符。对我的无知表示歉意,但除了评论之外,我该如何回应? - John Saltwell
你能把程序压缩到尽可能小的体积,然后在问题中发布吗? - David Heffernan
这里也有JEDI。很遗憾你没有展示整个程序,否则我可以尝试编译它。你的uses子句在哪里?通过阅读JEDI头文件,可以找到解决错误的方法。无论如何,你似乎认为你的问题在于理解C#。那不是你的问题。你可以很好地阅读MSDN文档。无需理解C#。你的问题是从FPC调用Win32 API。 - David Heffernan
当然,你说得没错,但这假定我在这方面有相当高的专业知识。尽管我已经从事编程多年,但这只是我的兼职工作,而且我从来没有那么擅长。如果我对Windows安全有足够的了解,那么理解Windows API就很容易了。实际上,我发现大多数MSDN关于安全等主题的文章一旦涉及到C代码就难以理解 - 因此必须查看其他人如何完成相同的任务,并尝试将他们的代码翻译成我能理解的语言。(因为反引号格式无法正常工作,所以仅上传了一个示例。) - John Saltwell
1个回答

1
这里是解决编译问题的方法。
调用 DuplicateTokenEx 实际上在第三个参数上失败了。查看声明,它是 LPSECURITY_ATTRIBUTES,即 ^TSecurityAttributes。现在,tokenAttributes 的类型是 TSecurityAttributes,因此您需要传递其地址。
If Not DuplicateTokenEx(..., @tokenAttributes, ...) then

同样地,在调用 AdjustTokenPrivileges 时。C# 代码如下:

AdjustTokenPrivileges(newToken, false, ref tokPrivs, 0, IntPtr.Zero, IntPtr.Zero)

翻译成中文就是:“如果转换为Pascal,代码如下:”
AdjustTokenPrivileges(NewToken, False, @TOKPrivs, 0, nil, nil)

我不知道代码是否能解决你的问题。我认为这超出了这个问题的范围-至少这是我的借口,我会坚持这一点!


谢谢你的帮助!那绝对是一个有用的提示,我会尝试并记住你的例子来解决剩下的问题。 - John Saltwell
程序仍无法编译,因此我已将整个程序上传到Dropbox,以防David(或任何其他慷慨的专家!)有机会浏览它。如有进一步提示,将不胜感激。https://www.dropbox.com/sh/ulvurtluroc4u34/Vhbl_tkgZc - John Saltwell
当然,我回答了你提出的问题。你希望这个进行多深入的探讨? - David Heffernan
无论如何,问题在于你的 uses 子句的顺序。在 JwaWindows 之前需要将 Windows 列出来。我真诚地相信我已经回答了你所问的问题。你还需要像我所描述的那样修复 AdjustTokenPrivileges 调用。然后是 CreateProcessAsUser。但你可以自己解决这个问题。函数声明在 jwawinbase 中。当参数类型不匹配时,查看声明并确保参数匹配。同时参考 MSDN 文档。 - David Heffernan
谢谢。我以为我按照您的建议做了,但应该再检查一下我的代码。试图将您的答案标记为有帮助,但似乎在允许之前我需要更多的积分。 - John Saltwell
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接