-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathUnitWin10.pas
443 lines (355 loc) · 11.2 KB
/
UnitWin10.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
unit UnitWin10;
//win10 兼容性的单元
interface
uses
ShlObj, shellapi, windows, SysUtils, Dialogs,
tlhelp32,
forms;
//win10 下用户可写的目录
(*
uses System.IOUtils;
//例如 C:\Users\administrator\AppData\Roaming
procedure TForm1.FormCreate(Sender: TObject);
var
S: string;
begin
{ 三种方法结果一致: C:\Users\wy\AppData\Roaming }
S := GetHomePath; // SysUtils, 能跨平台且简单, 在 Windows 下使用 SHGetFolderPath 完成
S := TPath.GetHomePath; // System.IOUtils
S := GetEnvironmentVariable('APPDATA'); // 以前一直用这个
end;
*)
//取 windows10 下的程序目录
//例如 C:\Users\administrator\AppData\Roaming
function AppPath(const appname:string; create:boolean=true):string;
//win10下取程序目录下的配置文件,如果在 win10 的 appdata 中没有的话就先复制
function win10ConfigFile(const appname:string; const fn:string):string;
//是否有管理员权限
function IsAdmin: Boolean;
//确实可用//判断程序是否以管理员身份运行
//http://blog.csdn.net/donglinshengan/article/details/18416645
//BOOL FindUacToken_v2()
function IsAdmin_v2: Boolean;
//写入文件的权限
function SetAdmin: Boolean;
implementation
//xp 以后版本,用户权限提醒
function WindowsVersion_highXP: Boolean;
var
VI: TOSVersionInfoA;
begin
Result := False;
VI.dwOSVersionInfoSize := SizeOf(TOSVersionInfoA);
//DWORD dwOSVersionInfoSize; //在使用GetVersionEx之前要将此初始化为结构的大小
//
//DWORD dwMajorVersion; //系统主版本号
//
//DWORD dwMinorVersion; //系统次版本号
//
//DWORD dwBuildNumber; //系统构建号
//
//DWORD dwPlatformId; //系统支持的平台(详见附1)
//
//TCHAR szCSDVersion[128]; //系统补丁包的名称
//
//WORD wServicePackMajor; //系统补丁包的主版本
//
//WORD wServicePackMinor; //系统补丁包的次版本
//
//WORD wSuiteMask; //标识系统上的程序组(详见附2)
//
//BYTE wProductType; //标识系统类型(详见附3)
//
//BYTE wReserved; //保留,未使用
if GetVersionExA(VI) then
begin
if VI.dwMajorVersion>5 then Result := True;
end;
end;
function win10:boolean;
var
VI: TOSVersionInfoA;
begin
Result := False;
VI.dwOSVersionInfoSize := SizeOf(TOSVersionInfoA);
//DWORD dwOSVersionInfoSize; //在使用GetVersionEx之前要将此初始化为结构的大小
//DWORD dwMajorVersion; //系统主版本号
//DWORD dwMinorVersion; //系统次版本号
//DWORD dwBuildNumber; //系统构建号
//DWORD dwPlatformId; //系统支持的平台(详见附1)
//TCHAR szCSDVersion[128]; //系统补丁包的名称
//WORD wServicePackMajor; //系统补丁包的主版本
//WORD wServicePackMinor; //系统补丁包的次版本
//WORD wSuiteMask; //标识系统上的程序组(详见附2)
//BYTE wProductType; //标识系统类型(详见附3)
//BYTE wReserved; //保留,未使用
if GetVersionExA(VI) then
begin
if VI.dwMajorVersion>5 then Result := True;
//win10 的 dwMinorVersion 应该是 2,dwMajorVersion 应该是6,所以就是 nt6.2//这里简单一点,大于 xp 就算好了
end;
end;
//windows 和各个目录
function GetShellPath(const itype:integer):string;
var
pidl: pItemIDList;
buffer: array[0..255] of char;
begin
{取指定的文件夹}
//SHGetSpecialFolderLocation(application.Handle, 28, pidl);
SHGetSpecialFolderLocation(application.Handle, itype, pidl);
SHGetPathFromIDList(pidl, buffer);
//memo1.Lines.Add(strpas(buffer));
Result := strpas(buffer);
end;
{
得到的结果是:C:\Users\用户名\AppData\Local
组合完毕是:C:\Users\用户名\AppData\Local\Google\Chrome\User Data
那个常数的更全代表意思如下:
'桌面',0
'所有用户桌面',25
'开始菜单程序',2
'所有用户开始菜单程序',23
'我的文档',5
'收藏夹',6
'所有用户收藏夹',31
'启动文件夹',7
'所有用户启动文件夹',24
'Recent文件夹',8
'发送到',9
'登陆用户开始菜单',11
'所有用户开始菜单',22
'网上邻居',19
'字体文件夹',20
'Template文件夹',21
'所有用户Template文件夹',45
'ApplicaionData 文件夹',26
'打印文件夹',27
'当前用户本地应用程序设置文件夹',28
'Internet临时文件夹',32
'Internet缓存文件夹',33
'当前用户历史文件夹',34
'所有用户应用程序设置文件夹',35
'Windows系统目录',36
'程序文件夹',38
'System32系统目录',37
'当前用户图片收藏夹',39
'当前用户文件夹',40
'公共文件夹',43
'管理工具',47
'登陆用户管理工具',48
'所有用户图片收藏夹',54
'所有用户视频收藏夹',55
'主题资源文件夹',56
'CD Burning',59
}
//取 windows10 下的程序目录
//例如 C:\Users\administrator\AppData\Roaming
function AppPath(const appname:string; create:boolean=true):string;
begin
if win10 then
begin
Result := GetShellPath(26);
if appname<>'' then
begin
Result := Result + '\' + appname + '\';
if create then
ForceDirectories(Result);
end;
end
else
begin
Result := ExtractFilePath(application.ExeName);
end;
end;
//win10下取程序目录下的配置文件,如果在 win10 的 appdata 中没有的话就先复制
function win10ConfigFile(const appname:string; const fn:string):string;
var
srcfn:string;
begin
srcfn := ExtractFilePath(application.ExeName) + fn;
if win10 then
begin
Result := UnitWin10.AppPath(appname) + fn;
copyfile(pansichar(srcfn), pansichar(Result), true);
end
else
begin
Result := ExtractFilePath(application.ExeName) + fn;
end;
end;
//确实可用//判断程序是否以管理员身份运行
//http://blog.csdn.net/donglinshengan/article/details/18416645
//BOOL FindUacToken_v2()
function IsAdmin_v2: Boolean;
var
hToken:THANDLE;// = 0;//clq add
hProcessSnap:THANDLE;// hProcessSnap = NULL;
bRet: Boolean;// = FALSE;
pe32:PROCESSENTRY32;
//pe32 = {0};
hProcess:THANDLE;
TokenIsElevated:DWORD;
dwReturnLength:DWORD;// = 0;
begin
Result := False;
bRet := False;
hProcessSnap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap = INVALID_HANDLE_VALUE)
then exit; //return FALSE;
FillMemory(@pe32, SizeOf(PROCESSENTRY32), 0);
pe32.dwSize := sizeof(PROCESSENTRY32);
hToken := 0;
//--------------------------------------------------
//http://blog.csdn.net/qq_26153041/article/details/52168264
//Open a handle to the access token for the calling process
//以查询方式打开 当前进程的Token,即是当前登录用户的Token
//if(!OpenProcessToken(GetCurrentProcess( ),TOKEN_QUERY,&hToken))
//{
// _tprintf(TEXT("OpenProcessToken failed with error %d\n"),GetLastError( ));
// return FALSE;
//}
//--------------------------------------------------
//hProcess := OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);
//if (OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken))
hProcess := GetCurrentProcess(); //clq add//用这个应该就可以了,因为原来是遍历所有的进程,这里只判断自己就行了
if (OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, hToken)) then
//if (OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, @hToken) = true) then
begin
TokenIsElevated := 0;
dwReturnLength := 0;
// 获取进程信息,以判断是否以管理员权限运行//(_TOKEN_INFORMATION_CLASS)20 似乎是 TokenElevation 的意思
//if (GetTokenInformation(hToken, (_TOKEN_INFORMATION_CLASS)20,&TokenIsElevated,sizeof(DWORD),&dwReturnLength))
if (GetTokenInformation(hToken, TTokenInformationClass(20),@TokenIsElevated,sizeof(DWORD),dwReturnLength)) then
begin
//if (dwReturnLength = sizeof(DWORD) && 1 = TokenIsElevated) // 说明是以管理员权限运行的
if (dwReturnLength = sizeof(DWORD)) and (1 = TokenIsElevated) then // 说明是以管理员权限运行的
begin
//printf("管理员\r\n");
Result := True;
(*
UCHAR InfoBuffer[ 512 ];
DWORD cbInfoBuffer = 512;
DWORD cchUser;
DWORD cchDomain;
TCHAR UserName[128];
TCHAR DomainName[128];
SID_NAME_USE snu;
// 再次获取进程信息,以判断是否是用户进程
if ( GetTokenInformation(hToken, TokenUser, InfoBuffer, cbInfoBuffer, &cbInfoBuffer) ) then
begin
bRet = LookupAccountSid(NULL, ((PTOKEN_USER)InfoBuffer)->User.Sid, UserName, &cchUser, DomainName, &cchDomain, &snu);
_tcslwr_s(UserName, 128);
_tcslwr_s(DomainName, 128);
if (NULL == _tcsstr(UserName, TEXT("system")) && NULL != _tcsstr(DomainName, TEXT("-pc"))) then
begin
Result := True; //return TRUE;
end;
end;
*)
end;
end;
CloseHandle(hToken);
end;
CloseHandle(hProcess);
CloseHandle (hProcessSnap);
//return bRet;
//bRet
end;//
//if AdjustProcessPrivilege(GetCurrentProcess,'SeDebugPrivilege') then //提升权限
//Memo1.Lines.Add('提升权限成功')
//else
//Memo1.Lines.Add('提升权限失败');
//提升进程令牌函数
function AdjustProcessPrivilege(ProcessHandle:THandle;Token_Name:Pchar):boolean;
var
Token:Cardinal;
TokenPri:_TOKEN_PRIVILEGES;
ProcessDest:int64;
l:DWORD;
begin
Result:=False;
if OpenProcessToken(ProcessHandle,TOKEN_Adjust_Privileges,Token) then
begin
if LookupPrivilegeValue(nil,Token_Name,ProcessDest) then
begin
TokenPri.PrivilegeCount:=1;
TokenPri.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
TokenPri.Privileges[0].Luid:=ProcessDest;
l:=0;
//更新进程令牌,成功返回TRUE
if AdjustTokenPrivileges(Token,False,TokenPri,sizeof(TokenPri),nil,l) then
Result:=True;
end;
end;
end;
//写入文件的权限
function SetAdmin: Boolean;
begin
//if AdjustProcessPrivilege(GetCurrentProcess,'SeDebugPrivilege') then //提升权限
//Memo1.Lines.Add('提升权限成功')
//else
//Memo1.Lines.Add('提升权限失败');
// SeDebugPrivilege 应该是杀进程需要的权限
//SeBackupPrivilege 应该是访问所有文件
if AdjustProcessPrivilege(GetCurrentProcess,'SeBackupPrivilege') then //提升权限
Result := True //提升权限成功
else
Result := False; //提升权限失败
if AdjustProcessPrivilege(GetCurrentProcess,'SeTakeOwnershipPrivilege') then //提升权限
//Result := True //提升权限成功
else
Result := False; //提升权限失败
if AdjustProcessPrivilege(GetCurrentProcess,'SeSecurityPrivilege') then //提升权限
//Result := True //提升权限成功
else
Result := False; //提升权限失败
end;
//有问题,不要用
//http://www.delphitop.com/html/xitong/246.html//有问题,不要用
function IsAdmin: Boolean;
const
SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = (value: (0, 0, 0, 0, 0, 5));
SECURITY_BUILTIN_DOMAIN_RID = $00000020;
DOMAIN_ALIAS_RID_ADMINS = $00000220;
var
hAccessToken: THandle;
ptgGroups: PTokenGroups;
dwInfoBufferSize: DWORD;
psidAdministrators: PSID;
x: Integer;
bSuccess: BOOL;
begin
Result := False;
bSuccess := OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True,
hAccessToken);
if Not bSuccess Then
begin
If GetLastError = ERROR_NO_TOKEN Then
bSuccess := OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, hAccessToken);
end;
if bSuccess Then
begin
GetMem(ptgGroups, 1024);
bSuccess := GetTokenInformation(hAccessToken, TokenGroups, ptgGroups, 1024, dwInfoBufferSize);
CloseHandle(hAccessToken);
if bSuccess Then
begin
AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0, psidAdministrators);
{$R-}
for x := 0 To ptgGroups.GroupCount - 1 Do
begin
if EqualSid(psidAdministrators, ptgGroups.Groups[x].Sid) Then
begin
Result := True;
Break;
end;
end;
{$R+}
FreeSid(psidAdministrators);
end;
FreeMem(ptgGroups);
end;
end;
end.