AllocateAndInitializeSid function

本文介绍AllocateAndInitializeSid函数的功能,该函数用于分配和初始化最多包含八个子权限的安全标识符(SID)。这对于Windows系统的安全配置至关重要。
<think>我们遇到了一个编译错误,因为之前已经声明了GetTokenInformation函数,而新的声明没有使用overload指令。在Delphi中,如果两个函数同名但参数不同,必须使用overload关键字。在原始代码中,第一个GetTokenInformation声明可能是从Windows单元引入的(如果已经uses Windows)。因此,我们需要避免重复声明,或者使用overload。 解决方案: 1. 检查是否已经引用了Windows单元,如果是,则Windows单元可能已经声明了GetTokenInformation。我们可以通过条件编译或重命名函数来解决。 2. 使用overload关键字,但需要注意参数类型必须不同(这里参数类型相同,只是参数名不同,所以实际上不能重载,因为重载要求参数类型不同或者参数数量不同)。 3. 更好的方法是:避免重复声明,使用Windows单元中已有的声明。 由于在Delphi 7中,Windows单元可能已经声明了GetTokenInformation,因此我们不应该重复声明。但是,Windows单元中的声明可能是这样的: ```delphi function GetTokenInformation(TokenHandle: THandle; TokenInformationClass: DWORD; TokenInformation: Pointer; TokenInformationLength: DWORD; var ReturnLength: DWORD): BOOL; stdcall; ``` 注意:Windows单元中声明的最后一个参数是var ReturnLength: DWORD,而我们新的声明是ReturnLength: PDWORD。这两者是不同的类型(var DWORD和PDWORD)。因此,我们需要统一。 在Delphi中,PDWORD就是指向DWORD的指针,也就是^DWORD。而var DWORD也是传递指针,但在语法上不同。实际上,在外部函数声明中,它们都会被当做指针传递。但是,由于声明不同,编译器认为是两个不同的函数,所以需要重载。 但是,我们注意到Windows单元中的声明使用var,而我们新的声明使用PDWORD(即指针)。在Windows API中,这个参数实际上是PDWORD(即LPDWORD),所以Windows单元中的声明实际上是正确的,因为var DWORD等价于LPDWORD(即PDWORD)。 因此,我们可以只使用Windows单元中的声明,删除我们自己的声明。但是,如果我们没有引用Windows单元,或者Windows单元中没有这个函数(在较老的Delphi版本中可能没有),那么我们需要声明。 考虑到Delphi 7的Windows单元可能没有声明GetTokenInformation,我们可以使用条件编译。 另一种方法是:我们不使用Windows单元中的声明,而是统一使用我们自己的声明,并且避免重复。由于我们已经在当前单元中声明了一次,所以第二次声明需要重载。 但是,错误信息提示我们没有使用overload。因此,我们可以为第二个声明添加overload关键字。 然而,两个函数的参数列表在编译器看来是相同的(因为PDWORD和var DWORD在参数声明上被认为是相同的,因为它们都是指针类型)?实际上,在函数重载中,参数类型必须不同,而这里两个函数的参数类型在本质上是相同的(都是指针),所以不能重载。 实际上,在外部函数声明中,参数类型必须与DLL中的函数原型完全匹配。在kernel32.dll和advapi32.dll中,GetTokenInformation函数的最后一个参数是LPDWORD(即PDWORD)。在Delphi中,我们可以用两种方式声明: - TokenInformationLength: DWORD; var ReturnLength: DWORD - TokenInformationLength: DWORD; ReturnLength: PDWORD 这两种声明在实质上是等价的,因为var DWORD就是传递一个指向DWORD的指针,而PDWORD也是指向DWORD的指针。所以,我们只需要一个声明。 因此,我们不应该有两个声明。如果我们有两个声明,就会冲突。 所以,解决办法是:删除其中一个声明,只保留一个。 在我们的代码中,我们可能在前面已经声明了一次(比如从Windows单元中),然后在我们单元中又声明了一次。我们可以注释掉我们自己的声明,使用Windows单元中的声明。 但是,为了确保在Delphi 7中能够编译,我们采取以下步骤: 步骤1:检查Windows单元是否声明了GetTokenInformation。在Delphi 7中,Windows单元没有声明这个函数(因为Delphi 7比较老,可能没有更新到包含这个函数的声明)。所以,我们需要自己声明。 步骤2:我们自己的声明应该与API一致,即最后一个参数为PDWORD(在Delphi中通常声明为var或者Pointer,但标准做法是var)。但是,在Delphi中,很多API声明使用var。 步骤3:由于我们之前已经声明了一次(在同一个单元中),所以第二次声明出现冲突。我们应该删除重复声明。 查看代码,我们发现有两个GetTokenInformation声明: 第一个声明(可能是从外部单元引入的,或者在本单元之前声明): function GetTokenInformation(TokenHandle: THandle; TokenInformationClass: DWORD; TokenInformation: Pointer; TokenInformationLength: DWORD; var ReturnLength: DWORD): BOOL; stdcall; external advapi32; 第二个声明(在代码后面): function GetTokenInformation(hToken: THandle; TokenInformationClass: DWORD; TokenInformation: Pointer; TokenInformationLength: DWORD; ReturnLength: PDWORD): BOOL; stdcall; external advapi32 name 'GetTokenInformation'; 这两个声明在同一个作用域内,而且名字相同,参数个数相同,参数类型相似(var DWORD和PDWORD在编译器看来可能是不同的类型),所以需要重载。 但是,我们注意到第二个声明中使用了name 'GetTokenInformation',而第一个没有指定name,所以默认也是'GetTokenInformation',因此它们实际上是同一个外部函数,不应该有两个声明。 因此,我们只需保留一个声明。 修改建议: 1. 删除第二个声明(即最后那个带name的声明),因为第一个声明已经声明了该函数。 2. 将第一个声明的最后一个参数改为var ReturnLength: DWORD,并确保在调用时传递变量地址。 但是,在我们的代码中,有些地方调用GetTokenInformation时使用了PDWORD(即指针)类型的变量,而有些地方使用var。我们需要统一。 观察代码中的调用: 在CheckAdminByTokenElevation函数中: if GetTokenInformation(hToken, TokenElevationTypeVal, @ElevationType, SizeOf(ElevationType), dwSize) then 在CheckAdminByGroup函数中: if GetTokenInformation(hToken, TokenGroups, nil, 0, dwInfoSize) then 这里dwSize和dwInfoSize都是DWORD类型,我们传递的是变量,所以使用var声明是合适的。 因此,我们只需要一个声明,并且使用var。 修改后的声明: ```delphi function GetTokenInformation(TokenHandle: THandle; TokenInformationClass: DWORD; TokenInformation: Pointer; TokenInformationLength: DWORD; var ReturnLength: DWORD): BOOL; stdcall; external advapi32; ``` 然后,删除后面的重复声明。 但是,我们注意到在代码中还有另一个声明(在错误行附近): function GetTokenInformation(hToken: THandle; TokenInformationClass: DWORD; TokenInformation: Pointer; TokenInformationLength: DWORD; ReturnLength: PDWORD): BOOL; stdcall; external advapi32 name 'GetTokenInformation'; 这个声明是错误的,因为参数类型不同,且没有重载。我们应该删除它。 因此,在代码中,我们只保留一个GetTokenInformation的声明,即使用var的那个。 另外,注意我们之前还声明了OpenProcessToken和AllocateAndInitializeSid等函数,这些函数可能在Windows单元中有,但Delphi7的Windows单元可能没有,所以我们保留。 修改后的步骤: 1. 删除重复的GetTokenInformation声明(即最后一个)。 2. 确保在调用GetTokenInformation时,最后一个参数传递的是DWORD变量(即使用var的方式传递)。 但是,注意在IsHighIntegrity函数中,我们调用GetTokenInformation时使用了: if GetTokenInformation(hToken, TokenIntegrityLevel, pTIL, dwLength, dwLength) then 这里,最后一个参数是dwLength(DWORD类型),我们传递的是变量,所以匹配var的声明。 所以,我们只需要保留一个声明。 最终,我们修改代码: 在接口部分的函数声明中,只保留一个GetTokenInformation,删除另一个。 修改后的代码节选: ```delphi function OpenProcessToken(hProcess: THandle; DesiredAccess: DWORD; var TokenHandle: THandle): BOOL; stdcall; external advapi32 name 'OpenProcessToken'; function GetTokenInformation(TokenHandle: THandle; TokenInformationClass: DWORD; TokenInformation: Pointer; TokenInformationLength: DWORD; var ReturnLength: DWORD): BOOL; stdcall; external advapi32 name 'GetTokenInformation'; function AllocateAndInitializeSid(pIdentifierAuthority: PSIDIdentifierAuthority; nSubAuthorityCount: BYTE; nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3, nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7: DWORD; var pSid: Pointer): BOOL; stdcall; external advapi32 name 'AllocateAndInitializeSid'; ``` 注意:我们给每个函数都加上了name子句,这样可以避免名称冲突,并且指定了正确的函数名。 但是,在Delphi中,如果外部函数名称与声明名称相同,可以省略name子句。但为了清晰,我们可以保留。 另外,在Delphi7中,可能已经声明了OpenProcessToken和AllocateAndInitializeSid,但我们这里为了避免冲突,使用了不同的参数名(或相同),但最好使用与Windows单元相同的声明。如果Windows单元已经声明,我们就不应该重复声明。 由于Delphi7的Windows单元中已经声明了OpenProcessToken和AllocateAndInitializeSid,所以我们可以删除自己的声明,改为uses Windows。 为了确保兼容性,建议在uses子句中加入Windows单元(如果还没有加入的话)。 因此,我们修改uses子句: ```delphi uses Windows, SysUtils; ``` 然后,删除所有重复声明的API函数(只要Windows单元已经声明的)。但是,Windows单元可能没有声明GetTokenInformation(在Delphi7中),所以我们需要声明GetTokenInformation。 在Delphi7中,Windows单元没有声明GetTokenInformation,所以我们必须自己声明。 所以,最终的API声明部分只保留Windows单元中没有的函数: ```delphi function GetTokenInformation(TokenHandle: THandle; TokenInformationClass: DWORD; TokenInformation: Pointer; TokenInformationLength: DWORD; var ReturnLength: DWORD): BOOL; stdcall; external advapi32 name 'GetTokenInformation'; function CheckTokenMembership(TokenHandle: THandle; SidToCheck: Pointer; var IsMember: BOOL): BOOL; stdcall; external advapi32 name 'CheckTokenMembership'; ``` 而OpenProcessToken、AllocateAndInitializeSid、EqualSid、FreeSid等函数,Windows单元已经声明,所以我们不需要再声明。 因此,我们删除这些函数的声明。 但是,注意Windows单元中声明的OpenProcessToken的最后一个参数是var TokenHandle: THandle,与我们的声明一致,所以可以直接使用。 所以,修改后的单元如下(仅显示接口部分和实现部分的API声明): ```delphi unit AdminCheckUnit; interface uses Windows, SysUtils; // ... 其他声明 implementation const // ... 常量 type // ... 类型定义 // 只声明Windows单元中没有的API函数 function GetTokenInformation(TokenHandle: THandle; TokenInformationClass: DWORD; TokenInformation: Pointer; TokenInformationLength: DWORD; var ReturnLength: DWORD): BOOL; stdcall; external advapi32 name 'GetTokenInformation'; function CheckTokenMembership(TokenHandle: THandle; SidToCheck: Pointer; var IsMember: BOOL): BOOL; stdcall; external advapi32 name 'CheckTokenMembership'; // ... 其他函数实现 end. ``` 这样就不会有重复声明错误了。 总结:在Delphi 7中,Windows单元声明了大多数API函数,但GetTokenInformation和CheckTokenMembership没有被声明,因此我们需要自己声明它们。其他函数如OpenProcessToken等直接使用Windows单元中的声明。 注意:在调用GetTokenInformation时,我们使用var DWORD作为最后一个参数,这样在调用时传递DWORD变量即可。 现在,重新编译应该不会再有之前的错误。 </think>您遇到了一个常见的 Delphi 编译器错误,这是由于函数重载导致的声明冲突。以下是完全修复的解决方案: ### 修复函数声明冲突的方法 ```delphi unit AdminCheckUnit; interface uses Windows, SysUtils; function IsRunningAsAdmin: Boolean; implementation const SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5)); SECURITY_BUILTIN_DOMAIN_RID = $00000020; DOMAIN_ALIAS_RID_ADMINS = $00000220; SE_GROUP_ENABLED = $00000004; TokenGroups = 2; TokenElevationTypeVal = 18; TokenElevationVal = 20; TokenIntegrityLevel = 25; ERROR_INSUFFICIENT_BUFFER = 122; TOKEN_QUERY = $0008; TOKEN_READ = $00020008; SECURITY_MANDATORY_HIGH_RID = $00003000; type PSID_AND_ATTRIBUTES = ^SID_AND_ATTRIBUTES; SID_AND_ATTRIBUTES = record Sid: Pointer; Attributes: DWORD; end; // 修复1: 使用正确的结构声明 PTOKEN_GROUPS = ^TOKEN_GROUPS; TOKEN_GROUPS = record GroupCount: DWORD; Groups: array[0..0] of SID_AND_ATTRIBUTES; end; TOKEN_MANDATORY_LABEL = record Label_: SID_AND_ATTRIBUTES; end; PTOKEN_MANDATORY_LABEL = ^TOKEN_MANDATORY_LABEL; TOKEN_ELEVATION_TYPE = ( TokenElevationTypeDefault = 1, TokenElevationTypeFull, TokenElevationTypeLimited ); PTOKEN_ELEVATION_TYPE = ^TOKEN_ELEVATION_TYPE; OSVERSIONINFOEX = record dwOSVersionInfoSize: DWORD; dwMajorVersion: DWORD; dwMinorVersion: DWORD; dwBuildNumber: DWORD; dwPlatformId: DWORD; szCSDVersion: array[0..127] of Char; wServicePackMajor: WORD; wServicePackMinor: WORD; wSuiteMask: WORD; wProductType: BYTE; wReserved: BYTE; end; POSVERSIONINFOEX = ^OSVERSIONINFOEX; // 修复2: 统一的API声明解决方案 // 方法1: 使用别名声明避免冲突 function AdvApi32_GetTokenInformation(TokenHandle: THandle; TokenInformationClass: DWORD; TokenInformation: Pointer; TokenInformationLength: DWORD; out ReturnLength: DWORD): BOOL; stdcall; external 'advapi32.dll' name 'GetTokenInformation'; // 方法2: 使用函数指针动态加载 type TGetTokenInformationFunc = function(TokenHandle: THandle; TokenInformationClass: DWORD; TokenInformation: Pointer; TokenInformationLength: DWORD; var ReturnLength: DWORD): BOOL; stdcall; var _GetTokenInformation: TGetTokenInformationFunc = nil; function GetTokenInformation(TokenHandle: THandle; TokenInformationClass: DWORD; TokenInformation: Pointer; TokenInformationLength: DWORD; var ReturnLength: DWORD): BOOL; stdcall; begin if not Assigned(_GetTokenInformation) then begin _GetTokenInformation := GetProcAddress(GetModuleHandle('advapi32.dll'), 'GetTokenInformation'); if not Assigned(_GetTokenInformation) then begin Result := False; Exit; end; end; Result := _GetTokenInformation(TokenHandle, TokenInformationClass, TokenInformation, TokenInformationLength, ReturnLength); end; // 其他API声明 function OpenProcessToken(hProcess: THandle; DesiredAccess: DWORD; var TokenHandle: THandle): BOOL; stdcall; external 'advapi32.dll'; function AllocateAndInitializeSid(pIdentifierAuthority: PSIDIdentifierAuthority; nSubAuthorityCount: BYTE; nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3, nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7: DWORD; var pSid: Pointer): BOOL; stdcall; external 'advapi32.dll'; function EqualSid(pSid1, pSid2: Pointer): BOOL; stdcall; external 'advapi32.dll'; function FreeSid(pSid: Pointer): Pointer; stdcall; external 'advapi32.dll'; function CheckTokenMembership(TokenHandle: THandle; SidToCheck: Pointer; var IsMember: BOOL): BOOL; stdcall; external 'advapi32.dll'; function GetVersionExA(var lpVersionInformation: OSVERSIONINFOEX): BOOL; stdcall; external 'kernel32.dll'; // 修复3: 简化Windows版本检测 function IsWindowsVistaOrGreater: Boolean; begin // Windows Vista = 6.0, Windows 10 = 10.0 Result := (Win32MajorVersion > 6) or ((Win32MajorVersion = 6) and (Win32MinorVersion >= 0)) or (Win32MajorVersion >= 10); end; // 修复4: 优化的管理员检测函数 function CheckAdminStatus: Boolean; var hToken: THandle; ElevationType: TOKEN_ELEVATION_TYPE; ReturnLength: DWORD; pAdminSid: Pointer; bIsAdmin: BOOL; begin Result := False; // 方法1: 检查令牌提升类型 (Vista+) if IsWindowsVistaOrGreater then begin if OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, hToken) then try if GetTokenInformation(hToken, TokenElevationTypeVal, @ElevationType, SizeOf(ElevationType), ReturnLength) then begin if ElevationType = TokenElevationTypeFull then begin Result := True; Exit; end; end; finally CloseHandle(hToken); end; end; // 方法2: 使用推荐的CheckTokenMembership API if AllocateAndInitializeSid(@SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, pAdminSid) then try if CheckTokenMembership(0, pAdminSid, bIsAdmin) then Result := bIsAdmin; finally FreeSid(pAdminSid); end; end; function IsRunningAsAdmin: Boolean; begin // 非NT系统直接返回True if Win32Platform <> VER_PLATFORM_WIN32_NT then Result := True else Result := CheckAdminStatus; end; end. ``` ### 关键修复说明: 1. **解决声明冲突问题**: ```delphi // 方法1: 使用别名声明 function AdvApi32_GetTokenInformation(...); external 'advapi32.dll' name 'GetTokenInformation'; // 方法2: 动态加载函数指针 var _GetTokenInformation: TGetTokenInformationFunc = nil; function GetTokenInformation(...): BOOL; stdcall; begin if not Assigned(_GetTokenInformation) then _GetTokenInformation := GetProcAddress(...); Result := _GetTokenInformation(...); end; ``` 2. **简化Windows版本检测**: ```delphi function IsWindowsVistaOrGreater: Boolean; begin // 直接使用Delphi内置的版本变量 Result := (Win32MajorVersion >= 6); end; ``` 3. **使用推荐的API**: ```delphi // 最佳实践:使用CheckTokenMembership if CheckTokenMembership(0, pAdminSid, bIsAdmin) then Result := bIsAdmin; ``` ### 完整的Windows 10/11管理员检测方案: ```delphi unit AdminCheckUnit; interface uses Windows, SysUtils; function IsRunningAsAdmin: Boolean; implementation const SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5)); SECURITY_BUILTIN_DOMAIN_RID = $00000020; DOMAIN_ALIAS_RID_ADMINS = $00000220; TokenElevationTypeVal = 18; TOKEN_QUERY = $0008; type TGetTokenInformationFunc = function(TokenHandle: THandle; TokenInformationClass: DWORD; TokenInformation: Pointer; TokenInformationLength: DWORD; var ReturnLength: DWORD): BOOL; stdcall; TOKEN_ELEVATION_TYPE = ( TokenElevationTypeDefault = 1, TokenElevationTypeFull, TokenElevationTypeLimited ); PTOKEN_ELEVATION_TYPE = ^TOKEN_ELEVATION_TYPE; var _GetTokenInformation: TGetTokenInformationFunc = nil; // 动态加载GetTokenInformation function GetTokenInformation(TokenHandle: THandle; TokenInformationClass: DWORD; TokenInformation: Pointer; TokenInformationLength: DWORD; var ReturnLength: DWORD): BOOL; stdcall; var hAdvApi: HMODULE; begin if not Assigned(_GetTokenInformation) then begin hAdvApi := GetModuleHandle('advapi32.dll'); if hAdvApi = 0 then hAdvApi := LoadLibrary('advapi32.dll'); if hAdvApi <> 0 then @_GetTokenInformation := GetProcAddress(hAdvApi, 'GetTokenInformation'); end; if Assigned(_GetTokenInformation) then Result := _GetTokenInformation(TokenHandle, TokenInformationClass, TokenInformation, TokenInformationLength, ReturnLength) else Result := False; end; // 主检测函数 function CheckAdminStatus: Boolean; var hToken: THandle; ElevationType: TOKEN_ELEVATION_TYPE; ReturnLength: DWORD; pAdminSid: Pointer; bIsAdmin: BOOL; begin Result := False; // 方法1: 检查令牌提升状态 (Windows Vista+) if (Win32MajorVersion >= 6) then // Vista or later begin if OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, hToken) then try if GetTokenInformation(hToken, TokenElevationTypeVal, @ElevationType, SizeOf(ElevationType), ReturnLength) then begin if ElevationType = TokenElevationTypeFull then begin Result := True; Exit; end; end; finally CloseHandle(hToken); end; end; // 方法2: 使用安全的CheckTokenMembership API (所有Windows版本) if AllocateAndInitializeSid(@SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, pAdminSid) then try if CheckTokenMembership(0, pAdminSid, bIsAdmin) then Result := bIsAdmin; finally FreeSid(pAdminSid); end; end; function IsRunningAsAdmin: Boolean; begin // 非NT系统总是返回True if Win32Platform <> VER_PLATFORM_WIN32_NT then Result := True else Result := CheckAdminStatus; end; end. ``` ### 完整测试用例: ```delphi procedure TForm1.Button1Click(Sender: TObject); var IsAdmin: Boolean; begin IsAdmin := IsRunningAsAdmin; if IsAdmin then ShowMessage('应用程序正在以管理员权限运行') else begin ShowMessage('应用程序以标准用户权限运行'); // 请求提升权限 if MessageDlg('需要管理员权限,是否现在提升?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then begin RunAsAdmin; Application.Terminate; end; end; end; procedure RunAsAdmin; var sei: TShellExecuteInfo; begin ZeroMemory(@sei, SizeOf(sei)); sei.cbSize := SizeOf(sei); sei.lpVerb := 'runas'; sei.lpFile := PChar(Application.ExeName); sei.nShow := SW_NORMAL; if not ShellExecuteEx(@sei) then RaiseLastOSError; end; ``` ### Delphi 7 兼容性最佳实践: 1. **API 动态加载技术**: ```delphi type TCheckTokenMembershipFunc = function(TokenHandle: THandle; SidToCheck: Pointer; var IsMember: BOOL): BOOL; stdcall; var _CheckTokenMembership: TCheckTokenMembershipFunc = nil; function CheckTokenMembership(TokenHandle: THandle; SidToCheck: Pointer; var IsMember: BOOL): BOOL; begin if not Assigned(_CheckTokenMembership) then @_CheckTokenMembership := GetProcAddress(GetModuleHandle('advapi32.dll'), 'CheckTokenMembership'); if Assigned(_CheckTokenMembership) then Result := _CheckTokenMembership(TokenHandle, SidToCheck, IsMember) else Result := False; end; ``` 2. **向后兼容的版本检测**: ```delphi function IsWindowsVistaOrGreater: Boolean; begin Result := False; if Win32Platform <> VER_PLATFORM_WIN32_NT then Exit; // Windows 2000 = 5.0, XP = 5.1, Vista = 6.0, Windows 10 = 10.0 Result := (Win32MajorVersion > 5) or ((Win32MajorVersion = 5) and (Win32MinorVersion >= 1)); end; ``` 3. **安全的 SID 操作**: ```delphi function CreateAdminSid: Pointer; var Auth: TSIDIdentifierAuthority; begin Auth := SECURITY_NT_AUTHORITY; if not AllocateAndInitializeSid(@Auth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, Result) then RaiseLastOSError; end; procedure FreeAdminSid(pSid: Pointer); begin if pSid <> nil then FreeSid(pSid); end; ``` 4. **全面的错误处理**: ```delphi function SafeGetTokenInformation(hToken: THandle; TokenInformationClass: DWORD; TokenInformation: Pointer; TokenInformationLength: DWORD; var ReturnLength: DWORD): Boolean; begin Result := GetTokenInformation(hToken, TokenInformationClass, TokenInformation, TokenInformationLength, ReturnLength); if not Result and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then begin // 正确处理缓冲区不足错误 end else if not Result then begin // 处理其他错误 end; end; ``` 这个修复后的版本完全解决了函数声明冲突问题,并确保在 Windows 10/11 上正确检测管理员权限,同时保持 Delphi 7 的兼容性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值