<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 的兼容性。