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 - "

我的帕斯卡版本:

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

Lazarus 在六个参数中的第五个抛出错误。

dmain.pas(189,110) 错误:arg no 的类型不兼容。5: Got "TOKEN_TYPE", expected "_TOKEN_TYPE" - 这表明我还没有理解参数在做什么。(将参数 5 更改为TokenImpersonation会引发相同的错误。)

再往下,我更加迷失:

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

我可以看到结构类型 LUID_AND_ATTRIBUTES 在 Windows API 中,但 Lazarus 似乎无法识别它。

简而言之,我在黑暗中摸索。我试过用谷歌搜索“C# for Pascal程序员”,但没有发现任何帮助。学习 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”

4

1 回答 1

1

以下是解决编译问题的方法。

DuplicateTokenEx对第三个参数的调用实际上失败了。查看声明,它是LPSECURITY_ATTRIBUTESwhich is ^TSecurityAttributes。现在,tokenAttributes是类型TSecurityAttributes,所以你需要传递它的地址:

If Not DuplicateTokenEx(..., @tokenAttributes, ...) then

同样在调用AdjustTokenPrivileges. C#代码是:

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

转换为帕斯卡将是:

AdjustTokenPrivileges(NewToken, False, @TOKPrivs, 0, nil, nil)

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

于 2013-03-23T20:43:20.043 回答