Delphi -- 创建 桌面、发送到...、快速启动栏、开始菜单、程序菜单、右键菜 单

{=================================================================
功 能:
创建 桌面、发送到...、快速启动栏、开始菜单、程序菜单、右键菜单 快捷方式
参 数:
FileName : 快捷方式执行文件名
Description : 快捷方式描述信息
Arguements : 快捷方式执行参数
ShowName : 快捷方式显示名称
Location : 快捷方式类别
id : 需设置状态的队列号(255 为设置)
CreateOrDelete: 是创建还是删除(默认为创建 true)
返 回 值: 无
备 注:
需要引用 Registry, ShlObj, ComObj, ActiveX, RegStr 单元
=================================================================}
procedure TMainForm.CreateShortcut(FileName,Description,Arguements,ShowName:
string;
Location: ShortcutType; id: byte; CreateOrDelete: boolean=true);
var
cObj :IUnknown;
sLink :IShellLink;
pFile :IPersistFile;
sDir,spath,key,tmp :string;
wFileName :WideString;
mReg :TRegistry;
begin
cObj :=CreateComObject(CLSID_ShellLink); //创建COM对象
sLink :=cObj as IShellLink; //COM对象转化为IShellLink型接口
pFile :=cObj as IPersistFile; //COM对象转化为IPersistFile型接口
//获取路径
sPath :=ExtractFilePath(FileName);
with sLink do begin
SetPath(PChar(FileName)); //设置执行文件名
SetArguments(PChar(arguements)); //设置执行参数
SetDescription(Pchar(Description)); //设置描述信息
SetWorkingDirectory(PChar(sPath)); //设置工作路径,即执行程序所在目录
end;
//获取各快捷方式的实际目录
mReg :=TRegistry.Create;
with mReg do begin
if Location=ST_CONTEXT then //添加右键菜单
begin
RootKey :=HKEY_CLASSES_ROOT;
tmp:= '*shell'+ShowName;
if CreateOrDelete then
begin
if OpenKey(tmp,true) then
begin
//用writestring将设置值写入打开的主键
WriteString('',ShowName+'(&k)');
CloseKey;
end;
if OpenKey(tmp+'command',true) then
begin
//command子键的内容是点击右键后选择相应项后要运行的程序;
//%1是在单击右键时选中的文件名
//WriteString(,'c:delphimyprogram.exe+"%1"');
WriteString('',FileName);
CloseKey;
end;
end
else
DeleteKey(tmp);
Free;
exit;
end;
RootKey :=HKEY_CURRENT_USER;
key :=REGSTR_PATH_EXPLORER; //Delphi在单元RegStr中定义的常量
tmp :=key + 'Shell Folders';
OpenKey(tmp, false);
case Location of
ST_DESKTOP: sDir :=ReadString('Desktop');
ST_SENDTO: sDir :=ReadString('SendTo');
ST_STARTMENU: sDir :=ReadString('Start Menu');
ST_PROGRAMS: sDir :=ReadString('Programs');
ST_QUICKLAUNCH:
begin
sDir :=ReadString('AppData');
sDir :=sDir + 'MicrosoftInternet ExplorerQuick Launch';
end;
end;
//生成快捷方式文件名
if ShowName='' then
begin
ShowName :=ChangeFileExt(FileName, '.Lnk');
ShowName :=ExtractFileName(ShowName);
end
else
ShowName:= ShowName+'.lnk';
if sDir<>'' then
begin
//生成快捷方式全路径名
wFileName :=sDir + '' + ShowName;
if (id<) then
begin
if FileExists(wFileName) then
//RzCheckGroup1.ItemChecked[id]:= true;
end
else
//保存或删除生成的快捷方式文件
if CreateOrDelete then
pFile.Save(PWChar(wFileName), false)
else
DeleteFile(wFileName);
end;
Free;
end;
end;

Delphi AES加密(转)

(**************************************************************)
(* Advanced Encryption Standard (AES) *)
(* Interface Unit v1.3 *)
(* *)
(* Copyright (c) 2002 Jorlen Young *)
(* *)
(* 说明: *)
(* 基于 ElASE.pas 单元封装 *)
(* *)
(* 这是一个 AES 加密算法的标准接口。 *)
(* 调用示例: *)
(* if not EncryptStream(src, key, TStream(Dest), keybit) then *)
(* showmessage('encrypt error'); *)
(* *)
(* if not DecryptStream(src, key, TStream(Dest), keybit) then *)
(* showmessage('encrypt error'); *)
(* *)
(* *** 一定要对Dest进行TStream(Dest) *** *)
(* ========================================================== *)
(* *)
(* 支持 128 / 192 / 256 位的密匙 *)
(* 默认情况下按照 128 位密匙操作 *)
(* *)
(**************************************************************) unit AES; interface {$IFDEF VER210}
{$WARN IMPLICIT_STRING_CAST OFF} //关闭警告
{$WARN IMPLICIT_STRING_CAST_LOSS OFF}
{$ENDIF}
uses
SysUtils, Classes, Math, ElAES; const
SDestStreamNotCreated = 'Dest stream not created.';
SEncryptStreamError = 'Encrypt stream error.';
SDecryptStreamError = 'Decrypt stream error.'; type
TKeyBit = (kb128, kb192, kb256); function StrToHex(Const str: AnsiString): AnsiString;
function HexToStr(const Str: AnsiString): AnsiString; function EncryptString(Value: AnsiString; Key: AnsiString;
KeyBit: TKeyBit = kb128): AnsiString;
function DecryptString(Value: AnsiString; Key: AnsiString;
KeyBit: TKeyBit = kb128): AnsiString; function EncryptStream(Src: TStream; Key: AnsiString;
var Dest: TStream; KeyBit: TKeyBit = kb128): Boolean;
function DecryptStream(Src: TStream; Key: AnsiString;
var Dest: TStream; KeyBit: TKeyBit = kb128): Boolean; procedure EncryptFile(SourceFile, DestFile: String;
Key: AnsiString; KeyBit: TKeyBit = kb128);
procedure DecryptFile(SourceFile, DestFile: String;
Key: AnsiString; KeyBit: TKeyBit = kb128); implementation function StrToHex(Const str: Ansistring): Ansistring;
asm
push ebx
push esi
push edi
test eax,eax
jz @@Exit
mov esi,edx //保存edx值,用来产生新字符串的地址
mov edi,eax //保存原字符串
mov edx,[eax-] //获得字符串长度
test edx,edx //检查长度
je @@Exit {Length(S) = 0}
mov ecx,edx //保存长度
Push ecx
shl edx,
mov eax,esi
{$IFDEF VER210}
movzx ecx, word ptr [edi-] {需要设置CodePage}
{$ENDIF}
call System.@LStrSetLength //设置新串长度
mov eax,esi //新字符串地址
Call UniqueString //产生一个唯一的新字符串,串位置在eax中
Pop ecx
@@SetHex:
xor edx,edx //清空edx
mov dl, [edi] //Str字符串字符
mov ebx,edx //保存当前的字符
shr edx, //右移4字节,得到高8位
mov dl,byte ptr[edx+@@HexChar] //转换成字符
mov [eax],dl //将字符串输入到新建串中存放
and ebx,$0F //获得低8位
mov dl,byte ptr[ebx+@@HexChar] //转换成字符
inc eax //移动一个字节,存放低位
mov [eax],dl
inc edi
inc eax
loop @@SetHex
@@Exit:
pop edi
pop esi
pop ebx
ret
@@HexChar: db '0123456789ABCDEF'
end; function HexToStr(const Str: AnsiString): AnsiString;
asm
push ebx
push edi
push esi
test eax,eax //为空串
jz @@Exit
mov edi,eax
mov esi,edx
mov edx,[eax-]
test edx,edx
je @@Exit
mov ecx,edx
push ecx
shr edx,
mov eax,esi //开始构造字符串
{$IFDEF VER210}
movzx ecx, word ptr [edi-] {需要设置CodePage}
{$ENDIF}
call System.@LStrSetLength //设置新串长度
mov eax,esi //新字符串地址
Call UniqueString //产生一个唯一的新字符串,串位置在eax中
Pop ecx
xor ebx,ebx
xor esi,esi
@@CharFromHex:
xor edx,edx
mov dl, [edi] //Str字符串字符
cmp dl, '' //查看是否在0到f之间的字符
JB @@Exit //小于0,退出
cmp dl,'' //小于=9
ja @@DoChar//CompOkNum
sub dl,''
jmp @@DoConvert
@@DoChar:
//先转成大写字符
and dl,$DF
cmp dl,'F'
ja @@Exit //大于F退出
add dl,
sub dl,'A'
@@DoConvert: //转化
inc ebx
cmp ebx,
je @@Num1
xor esi,esi
shl edx,
mov esi,edx
jmp @@Num2
@@Num1:
add esi,edx
mov edx,esi
mov [eax],dl
xor ebx,ebx
inc eax
@@Num2:
dec ecx
inc edi
test ecx,ecx
jnz @@CharFromHex
@@Exit:
pop esi
pop edi
pop ebx
end; { -- 字符串加密函数 默认按照 128 位密匙加密 -- }
function EncryptString(Value: AnsiString; Key: AnsiString;
KeyBit: TKeyBit = kb128): AnsiString;
var
{$IFDEF VER210}
SS,DS: TMemoryStream;
{$ELSE}
SS, DS: TStringStream;
{$ENDIF}
Size: Int64;
AESKey128: TAESKey128;
AESKey192: TAESKey192;
AESKey256: TAESKey256;
st: AnsiString;
begin
Result := '';
{$IFDEF VER210}
ss := TMemoryStream.Create;
SS.WriteBuffer(PAnsiChar(Value)^,Length(Value));
DS := TMemoryStream.Create;
{$ELSE}
SS := TStringStream.Create(Value);
DS := TStringStream.Create('');
{$ENDIF}
try
Size := SS.Size;
DS.WriteBuffer(Size, SizeOf(Size));
{ -- 128 位密匙最大长度为 16 个字符 -- }
if KeyBit = kb128 then
begin
FillChar(AESKey128, SizeOf(AESKey128), );
Move(PAnsiChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));
EncryptAESStreamECB(SS, , AESKey128, DS);
end;
{ -- 192 位密匙最大长度为 24 个字符 -- }
if KeyBit = kb192 then
begin
FillChar(AESKey192, SizeOf(AESKey192), );
Move(PAnsiChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));
EncryptAESStreamECB(SS, , AESKey192, DS);
end;
{ -- 256 位密匙最大长度为 32 个字符 -- }
if KeyBit = kb256 then
begin
FillChar(AESKey256, SizeOf(AESKey256), );
Move(PAnsiChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));
EncryptAESStreamECB(SS, , AESKey256, DS);
end;
{$IFDEF VER210}
SetLength(st,Ds.Size);
DS.Position := ;
DS.ReadBuffer(PAnsiChar(st)^,DS.Size);
Result := StrToHex(st);
{$ELSE}
Result := StrToHex(DS.DataString);
{$ENDIF}
finally
SS.Free;
DS.Free;
end;
end; { -- 字符串解密函数 默认按照 128 位密匙解密 -- }
function DecryptString(Value: AnsiString; Key: AnsiString;
KeyBit: TKeyBit = kb128): AnsiString;
var
SS, DS: TStringStream;
Size: Int64;
AESKey128: TAESKey128;
AESKey192: TAESKey192;
AESKey256: TAESKey256;
begin
Result := '';
SS := TStringStream.Create(HexToStr(Value));
DS := TStringStream.Create('');
try
Size := SS.Size;
SS.ReadBuffer(Size, SizeOf(Size));
{ -- 128 位密匙最大长度为 16 个字符 -- }
if KeyBit = kb128 then
begin
FillChar(AESKey128, SizeOf(AESKey128), );
Move(PAnsiChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));
DecryptAESStreamECB(SS, SS.Size - SS.Position, AESKey128, DS);
end;
{ -- 192 位密匙最大长度为 24 个字符 -- }
if KeyBit = kb192 then
begin
FillChar(AESKey192, SizeOf(AESKey192), );
Move(PAnsiChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));
DecryptAESStreamECB(SS, SS.Size - SS.Position, AESKey192, DS);
end;
{ -- 256 位密匙最大长度为 32 个字符 -- }
if KeyBit = kb256 then
begin
FillChar(AESKey256, SizeOf(AESKey256), );
Move(PAnsiChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));
DecryptAESStreamECB(SS, SS.Size - SS.Position, AESKey256, DS);
end;
Result := DS.DataString;
finally
SS.Free;
DS.Free;
end;
end; { 流加密函数, default keybit: 128bit }
function EncryptStream(Src: TStream; Key: AnsiString;
var Dest: TStream; KeyBit: TKeyBit = kb128): Boolean;
var
Count: Int64;
AESKey128: TAESKey128;
AESKey192: TAESKey192;
AESKey256: TAESKey256;
begin
if Dest = nil then
begin
raise Exception.Create(SDestStreamNotCreated);
Result:= False;
Exit;
end; try
Src.Position:= ;
Count:= Src.Size;
Dest.Write(Count, SizeOf(Count));
{ -- 128 位密匙最大长度为 16 个字符 -- }
if KeyBit = kb128 then
begin
FillChar(AESKey128, SizeOf(AESKey128), );
Move(PAnsiChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));
EncryptAESStreamECB(Src, , AESKey128, Dest);
end;
{ -- 192 位密匙最大长度为 24 个字符 -- }
if KeyBit = kb192 then
begin
FillChar(AESKey192, SizeOf(AESKey192), );
Move(PAnsiChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));
EncryptAESStreamECB(Src, , AESKey192, Dest);
end;
{ -- 256 位密匙最大长度为 32 个字符 -- }
if KeyBit = kb256 then
begin
FillChar(AESKey256, SizeOf(AESKey256), );
Move(PAnsiChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));
EncryptAESStreamECB(Src, , AESKey256, Dest);
end; Result := True;
except
raise Exception.Create(SEncryptStreamError);
Result:= False;
end;
end; { 流解密函数, default keybit: 128bit }
function DecryptStream(Src: TStream; Key: AnsiString;
var Dest: TStream; KeyBit: TKeyBit = kb128): Boolean;
var
Count, OutPos: Int64;
AESKey128: TAESKey128;
AESKey192: TAESKey192;
AESKey256: TAESKey256;
begin
if Dest = nil then
begin
raise Exception.Create(SDestStreamNotCreated);
Result:= False;
Exit;
end; try
Src.Position:= ;
OutPos:= Dest.Position;
Src.ReadBuffer(Count, SizeOf(Count));
{ -- 128 位密匙最大长度为 16 个字符 -- }
if KeyBit = kb128 then
begin
FillChar(AESKey128, SizeOf(AESKey128), );
Move(PAnsiChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));
DecryptAESStreamECB(Src, Src.Size - Src.Position,
AESKey128, Dest);
end;
{ -- 192 位密匙最大长度为 24 个字符 -- }
if KeyBit = kb192 then
begin
FillChar(AESKey192, SizeOf(AESKey192), );
Move(PAnsiChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));
DecryptAESStreamECB(Src, Src.Size - Src.Position,
AESKey192, Dest);
end;
{ -- 256 位密匙最大长度为 32 个字符 -- }
if KeyBit = kb256 then
begin
FillChar(AESKey256, SizeOf(AESKey256), );
Move(PAnsiChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));
DecryptAESStreamECB(Src, Src.Size - Src.Position,
AESKey256, Dest);
end;
Dest.Size := OutPos + Count;
Dest.Position := OutPos; Result := True;
except
raise Exception.Create(SDecryptStreamError);
Result:= False;
end;
end; { -- 文件加密函数 默认按照 128 位密匙解密 -- }
procedure EncryptFile(SourceFile, DestFile: String;
Key: AnsiString; KeyBit: TKeyBit = kb128);
var
SFS, DFS: TFileStream;
Size: Int64;
AESKey128: TAESKey128;
AESKey192: TAESKey192;
AESKey256: TAESKey256;
begin
SFS := TFileStream.Create(SourceFile, fmOpenRead);
try
DFS := TFileStream.Create(DestFile, fmCreate);
try
Size := SFS.Size;
DFS.WriteBuffer(Size, SizeOf(Size));
{ -- 128 位密匙最大长度为 16 个字符 -- }
if KeyBit = kb128 then
begin
FillChar(AESKey128, SizeOf(AESKey128), );
Move(PAnsiChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));
EncryptAESStreamECB(SFS, , AESKey128, DFS);
end;
{ -- 192 位密匙最大长度为 24 个字符 -- }
if KeyBit = kb192 then
begin
FillChar(AESKey192, SizeOf(AESKey192), );
Move(PAnsiChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));
EncryptAESStreamECB(SFS, , AESKey192, DFS);
end;
{ -- 256 位密匙最大长度为 32 个字符 -- }
if KeyBit = kb256 then
begin
FillChar(AESKey256, SizeOf(AESKey256), );
Move(PAnsiChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));
EncryptAESStreamECB(SFS, , AESKey256, DFS);
end;
finally
DFS.Free;
end;
finally
SFS.Free;
end;
end; { -- 文件解密函数 默认按照 128 位密匙解密 -- }
procedure DecryptFile(SourceFile, DestFile: String;
Key: AnsiString; KeyBit: TKeyBit = kb128);
var
SFS, DFS: TFileStream;
Size: Int64;
AESKey128: TAESKey128;
AESKey192: TAESKey192;
AESKey256: TAESKey256;
begin
SFS := TFileStream.Create(SourceFile, fmOpenRead);
try
SFS.ReadBuffer(Size, SizeOf(Size));
DFS := TFileStream.Create(DestFile, fmCreate);
try
{ -- 128 位密匙最大长度为 16 个字符 -- }
if KeyBit = kb128 then
begin
FillChar(AESKey128, SizeOf(AESKey128), );
Move(PAnsiChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));
DecryptAESStreamECB(SFS, SFS.Size - SFS.Position, AESKey128, DFS);
end;
{ -- 192 位密匙最大长度为 24 个字符 -- }
if KeyBit = kb192 then
begin
FillChar(AESKey192, SizeOf(AESKey192), );
Move(PAnsiChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));
DecryptAESStreamECB(SFS, SFS.Size - SFS.Position, AESKey192, DFS);
end;
{ -- 256 位密匙最大长度为 32 个字符 -- }
if KeyBit = kb256 then
begin
FillChar(AESKey256, SizeOf(AESKey256), );
Move(PAnsiChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));
DecryptAESStreamECB(SFS, SFS.Size - SFS.Position, AESKey256, DFS);
end;
DFS.Size := Size;
finally
DFS.Free;
end;
finally
SFS.Free;
end;
end;
end.

Delphi 极速字符串替换函数

//此极速字符串替换函数为[盒子论坛hq200306兄]所作,在此感谢!亲测原本48秒的长文本替换操作,现在只要几十毫秒不到!

function PosX(const SubStr, Str: string; Offset: Integer): Integer;
var
I, LIterCnt, L, J: Integer;
PSubStr, PS: PChar;
begin
L := Length(SubStr);
{ Calculate the number of possible iterations. Not valid if Offset < 1. }
LIterCnt := Length(Str) - Offset - L + ; { Only continue if the number of iterations is positive or zero (there is space to check) }
if (Offset > ) and (LIterCnt >= ) and (L > ) then
begin
PSubStr := PChar(SubStr);
PS := PChar(Str);
Inc(PS, Offset - ); for I := to LIterCnt do
begin
J := ;
while (J >= ) and (J < L) do
begin
if UpCase(PS[I + J]) = UpCase(PSubStr[J]) then
Inc(J)
else
J := -;
end;
if J >= L then
Exit(I + Offset);
end;
end; Result := ;
end; function StringReplaceEx(const st, oldSubstr, newSubStr: string): string;
var
idx, len: Integer;
iStart: Integer;
sb: TStringBuilder;
begin
len := Length(oldSubstr);
iStart := ;
sb := TStringBuilder.Create;
try
repeat
idx := posX(oldSubstr, st, iStart);
if idx > then
begin
sb.Append(Copy(st, iStart, idx - iStart));
sb.Append(newSubStr);
iStart := idx + len;
end;
until idx <= ;
sb.Append(Copy(st, iStart, length(st)));
Result := sb.ToString;
finally
sb.Free;
end;
end;

Delphi 检测用户超过多长时间没有操作键盘或鼠标

procedure TForm1.Timer1Timer(Sender: TObject);
var vLastInputInfo: TLastInputInfo;
begin
vLastInputInfo.cbSize := SizeOf(vLastInputInfo);
GetLastInputInfo(vLastInputInfo);
if GetTickCount - vLastInputInfo.dwTime > then
begin
timer1.Enabled:= false;
showmessage('超过5秒,用户未动鼠标!');
end;
end; function StopTime: integer;//返回没有键盘和鼠标事件的时间
var LInput: TLastInputInfo;
begin
LInput.cbSize := SizeOf(TLastInputInfo);
GetLastInputInfo(LInput);
Result := (GetTickCount()- LInput.dwTime)div ;// 微妙换成秒
end;
procedure TForm1.Timer1Timer(Sender: TObject);// Timer 事件
begin
if StopTime>= then
Showmessage('用户已经1分钟没有动键盘鼠标了!');
end;

Delphi编程实现调用系统图标

uses shellapi;

第一步  取得系统的图标列表的句柄,将之赋予一个图像列表控件。
procedure GetSystemImageList(imagelist: TImageList);
var
SysIL: THandle;
SFI: TSHFileInfo;
begin
// 取小图标,如果将SHGFI_SMALLICON替换成
// SHGFI_LARGEICON则表示取大图标
SysIL := SHGetFileInfo('', , SFI, SizeOf(SFI),
SHGFI_SYSICONINDEX or SHGFI_SMALLICON);
if SysIL <> then
begin
// 将imagelist的图像列表句柄指向系统图像句柄
imagelist.Handle := SysIL;
// 防止组件释放时释放图像句柄,很重要
imagelist.ShareImages := TRUE;
end;
end; 第二步 取得要处理文件的图标索引
//取一个文件的图标索引
function GetIconIndex(const AFile: string; Attrs: DWORD): integer;
// Attrs可以为表示文件或路径FILE_ATTRIBUTE_NORMAL or FILE_ATTRIBUTE_DIRECTORY
var
SFI: TSHFileInfo;
begin
SHGetFileInfo(PChar(AFile), Attrs, SFI, SizeOf(TSHFileInfo),
SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES);
Result := SFI.iIcon;
end; 实例调用:
//如在TreeView中得到c:\mydir的图标,因为是路径所以要加上路径的标志
aNode.ImageIndex := GetIconIndex('c:\mydir\',
FILE_ATTRIBUTE_NORMAL or FILE_ATTRIBUTE_DIRECTORY);
//如在TreeView中得到c:\index.html的图标
aNode.ImageIndex := GetIconIndex('c:\index.html',FILE_ATTRIBUTE_NORMAL);

AES.pas 单元文件

  AES crypt algorithm pascal unit
base on AVR231's aes code
EMAIL: Shaoziyang@gmail.com
Web: http://avrubd.googlepages.com by Shaoziyang 2008.6 *) unit aes; interface uses
SysUtils; const
//!< Lower 8 bits of (x^8+x^4+x^3+x+1), ie. (x^4+x^3+x+1).
BPOLY = $1B; //!< Block size in number of bytes.
BLOCKSIZE = ; procedure aesKey(key: PByteArray; len: Integer);
procedure aesEncInit;
procedure aesEncrypt(buffer, chainBlock: PByteArray);
procedure aesDecInit;
procedure aesDecrypt(buffer, chainBlock: PByteArray); implementation var
kTable: array[..] of Byte =
(
$D0, $, $3F, $8C, $, $, $, $D8,
$, $, $E3, $, $, $D8, $, $AD,
$EA, $8B, $2A, $, $, $E9, $B0, $,
$, $B3, $, $, $0A, $C3, $, $3C
); block1: array[..] of Byte; //!< Workspace 1.
block2: array[..] of Byte; //!< Worksapce 2.
tempbuf: array[..] of Byte; powTbl: PByteArray; //!< Final location of exponentiation lookup table.
logTbl: PByteArray; //!< Final location of logarithm lookup table.
sBox: PByteArray; //!< Final location of s-box.
sBoxInv: PByteArray; //!< Final location of inverse s-box.
expandedKey: PByteArray; //!< Final location of expanded key. ROUNDS: Byte = ; //!< Number of rounds.
KEYLENGTH: Byte = ; //!< Key length in number of bytes. procedure aesKey(key: PByteArray; len: Integer);
var
i: Integer;
begin
if len <= then
begin
ROUNDS := ;
KEYLENGTH := ;
end
else
begin
ROUNDS := ;
KEYLENGTH := ;
end;
for i := to KEYLENGTH- do
kTable[i] := key^[i];
end; function CalcDat(t: Byte): Byte;
begin
if (t and $) = $ then
Result := ((t * ) xor BPOLY)
else
Result := (t * );
end; procedure CalcPowLog(powTbl, logTbl: PByteArray);
var
i, t: Byte;
begin
i := ;
t := ;
repeat
// Use 0x03 as root for exponentiation and logarithms.
powTbl^[i] := t;
logTbl^[t] := i;
i := i + ; // Muliply t by 3 in GF(2^8).
t := t xor CalcDat(t);
until (t = ); // Cyclic properties ensure that i < 255. powTbl^[] := powTbl^[]; // 255 = '-0', 254 = -1, etc.
end; procedure CalcSBox(sBox: PByteArray);
var
i, rot: Byte;
temp: Byte;
Result: Byte;
begin
// Fill all entries of sBox[].
i := ;
repeat
//Inverse in GF(2^8).
if (i > ) then
begin
temp := powTbl^[ - logTbl^[i]];
end
else
begin
temp := ;
end; // Affine transformation in GF(2).
Result := temp xor $; // Start with adding a vector in GF(2).
for rot := to do
begin
// Rotate left.
temp := (temp shl ) or (temp shr ); // Add rotated byte in GF(2).
Result := Result xor temp;
end; // Put result in table.
sBox^[i] := Result;
i := i + ;
until (i = );
end; procedure CalcSBoxInv(sBox, sBoxInv: PByteArray);
var
i, j: Byte;
begin
i := ;
j := ;
// Iterate through all elements in sBoxInv using i.
repeat // Search through sBox using j.
repeat
// Check if current j is the inverse of current i.
if (sBox^[j] = i) then
begin
// If so, set sBoxInc and indicate search finished.
sBoxInv^[i] := j;
j := ;
end;
j := j + ;
until (j = );
i := i + ;
until (i = );
end; procedure CycleLeft(row: PByteArray);
var
temp: Byte;
begin
// Cycle 4 bytes in an array left once.
temp := row^[];
row^[] := row^[];
row^[] := row^[];
row^[] := row^[];
row^[] := temp;
end; procedure InvMixColumn(column: PByteArray);
var
r0, r1, r2, r3: Byte;
begin r0 := column^[] xor column^[] xor column^[];
r1 := column^[] xor column^[] xor column^[];
r2 := column^[] xor column^[] xor column^[];
r3 := column^[] xor column^[] xor column^[]; column^[] := CalcDat(column^[]);
column^[] := CalcDat(column^[]);
column^[] := CalcDat(column^[]);
column^[] := CalcDat(column^[]); r0 := r0 xor column^[] xor column^[];
r1 := r1 xor column^[] xor column^[];
r2 := r2 xor column^[] xor column^[];
r3 := r3 xor column^[] xor column^[]; column^[] := CalcDat(column^[]);
column^[] := CalcDat(column^[]);
column^[] := CalcDat(column^[]);
column^[] := CalcDat(column^[]); r0 := r0 xor column^[] xor column^[];
r1 := r1 xor column^[] xor column^[];
r2 := r2 xor column^[] xor column^[];
r3 := r3 xor column^[] xor column^[]; column^[] := CalcDat(column^[]);
column^[] := CalcDat(column^[]);
column^[] := CalcDat(column^[]);
column^[] := CalcDat(column^[]); column^[] := column^[] xor column^[] xor column^[] xor column^[];
r0 := r0 xor column^[];
r1 := r1 xor column^[];
r2 := r2 xor column^[];
r3 := r3 xor column^[]; column^[] := r0;
column^[] := r1;
column^[] := r2;
column^[] := r3;
end; procedure SubBytes(bytes: PByteArray; count: Byte);
var
i: Byte;
begin
i := ;
repeat
bytes^[i] := sBox^[bytes^[i]]; // Substitute every byte in state.
i := i + ;
count := count - ;
until (count = );
end; procedure InvSubBytesAndXOR(bytes, key: PByteArray; count: Byte);
var
i: Byte;
begin
i := ;
repeat
// *bytes = sBoxInv[ *bytes ] ^ *key; // Inverse substitute every byte in state and add key.
bytes^[i] := block2[bytes^[i]] xor key^[i]; // Use block2 directly. Increases speed.
i := i + ;
count := count - ;
until (count = );
end; procedure InvShiftRows(state: PByteArray);
var
temp: Byte;
begin
// Note: State is arranged column by column. // Cycle second row right one time.
temp := state^[ + * ];
state^[ + * ] := state^[ + * ];
state^[ + * ] := state^[ + * ];
state^[ + * ] := state^[ + * ];
state^[ + * ] := temp; // Cycle third row right two times.
temp := state^[ + * ];
state^[ + * ] := state^[ + * ];
state^[ + * ] := temp;
temp := state^[ + * ];
state^[ + * ] := state^[ + * ];
state^[ + * ] := temp; // Cycle fourth row right three times, ie. left once.
temp := state^[ + * ];
state^[ + * ] := state^[ + * ];
state^[ + * ] := state^[ + * ];
state^[ + * ] := state^[ + * ];
state^[ + * ] := temp;
end; procedure InvMixColumns(state: PByteArray);
begin
InvMixColumn(@state[ * ]);
InvMixColumn(@state[ * ]);
InvMixColumn(@state[ * ]);
InvMixColumn(@state[ * ]);
end; procedure XORBytes(bytes1, bytes2: PByteArray; count: Byte);
var
i: Integer;
begin
i := ;
repeat
bytes1^[i] := bytes1^[i] xor bytes2^[i]; // Add in GF(2), ie. XOR.
i := i + ;
count := count - ;
until (count = );
end; procedure CopyBytes(a, b: PByteArray; count: Byte);
var
i: Byte;
begin
i := ;
repeat
a^[i] := b^[i];
i := i + ;
count := count - ;
until (count = );
end; procedure KeyExpansion(expandedKey: PByteArray);
var
temp: array[..] of Byte;
i: Byte;
Rcon: array[..] of Byte; // Round constant.
key: PByte;
begin
Rcon[] := ;
Rcon[] := ;
Rcon[] := ;
Rcon[] := ; key := @kTable; // Copy key to start of expanded key.
{i := KEYLENGTH;
repeat
expandedKey^[0] := key^;
inc(PByte(expandedKey), 1);
inc(key, 1);
i := i - 1;
until (i = 0);}
CopyBytes(expandedKey, PByteArray(key), KEYLENGTH);
Inc(PByte(expandedKey), KEYLENGTH); // Prepare last 4 bytes of key in temp.
dec(PByte(expandedKey), );
temp[] := expandedKey^[];
temp[] := expandedKey^[];
temp[] := expandedKey^[];
temp[] := expandedKey^[];
Inc(PByte(expandedKey), ); // Expand key.
i := KEYLENGTH;
while (i < BLOCKSIZE * (ROUNDS + )) do
begin
if KEYLENGTH > then
begin
// Are we at the start of a multiple of the key size?
if ((i mod KEYLENGTH) = ) then
begin
CycleLeft(@temp); // Cycle left once.
SubBytes(@temp, ); // Substitute each byte.
XORBytes(@temp, @Rcon, ); // Add constant in GF(2).
Rcon[] := CalcDat(Rcon[]); // Keysize larger than 24 bytes, ie. larger that 192 bits?
end
// Are we right past a block size?
else
if ((i mod KEYLENGTH) = BLOCKSIZE) then
SubBytes(@temp, ); // Substitute each byte.
end
else
begin
if ((i mod KEYLENGTH) = ) then
begin
CycleLeft(@temp); // Cycle left once.
SubBytes(@temp, ); // Substitute each byte.
XORBytes(@temp, @Rcon, ); // Add constant in GF(2).
Rcon[] := CalcDat(Rcon[]);
end;
end; // Add bytes in GF(2) one KEYLENGTH away.
dec(PByte(expandedKey), KEYLENGTH);
XORBytes(@temp, expandedKey, );
Inc(PByte(expandedKey), KEYLENGTH); // Copy result to current 4 bytes.
{expandedKey[0] := temp[0];
expandedKey[1] := temp[1];
expandedKey[2] := temp[2];
expandedKey[3] := temp[3];}
CopyBytes(expandedKey, @temp, );
Inc(PByte(expandedKey), );
i := i + ; // Next 4 bytes.
end;
end; procedure InvCipher(block, expandedKey: PByteArray);
var
round: Byte;
begin
round := ROUNDS - ;
Inc(PByte(expandedKey), BLOCKSIZE * ROUNDS); XORBytes(block, expandedKey, );
dec(PByte(expandedKey), BLOCKSIZE); repeat
InvShiftRows(block);
InvSubBytesAndXOR(block, expandedKey, );
dec(PByte(expandedKey), BLOCKSIZE);
InvMixColumns(block);
round := round - ;
until (round = ); InvShiftRows(block);
InvSubBytesAndXOR(block, expandedKey, );
end; procedure aesDecInit;
begin
powTbl := @block1;
logTbl := @block2;
CalcPowLog(powTbl, logTbl); sBox := @tempbuf;
CalcSBox(sBox); expandedKey := @block1;
KeyExpansion(expandedKey); sBoxInv := @block2; // Must be block2.
CalcSBoxInv(sBox, sBoxInv);
end; procedure aesDecrypt(buffer, chainBlock: PByteArray);
var
temp: array[..BLOCKSIZE - ] of Byte;
begin
CopyBytes(@temp, buffer, BLOCKSIZE);
InvCipher(buffer, expandedKey);
XORBytes(buffer, chainBlock, BLOCKSIZE);
CopyBytes(chainBlock, @temp, BLOCKSIZE);
end; function Multiply(num, factor: Byte): Byte;
var
mask: Byte;
begin
mask := ;
Result := ;
while (mask <> ) do
begin
// Check bit of factor given by mask.
if ((mask and factor) <> ) then
begin
// Add current multiple of num in GF(2).
Result := Result xor num;
end; // Shift mask to indicate next bit.
mask := mask shl ; // Double num.
num := CalcDat(num);
end;
end; function DotProduct(vector1, vector2: PByteArray): Byte;
begin
Result := ;
Result := Result xor Multiply(vector1^[], vector2^[]);
Inc(PByte(vector1));
Inc(PByte(vector2));
Result := Result xor Multiply(vector1^[], vector2^[]);
Inc(PByte(vector1));
Inc(PByte(vector2));
Result := Result xor Multiply(vector1^[], vector2^[]);
Inc(PByte(vector1));
Inc(PByte(vector2));
Result := Result xor Multiply(vector1^[], vector2^[]);
end; procedure MixColumn(column: PByteArray);
var
// Prepare first row of matrix twice, to eliminate need for cycling.
row: array[..] of Byte;
Result: array[..] of Byte;
begin
row[] := $;
row[] := $;
row[] := $;
row[] := $;
row[] := $;
row[] := $;
row[] := $;
row[] := $; // Take dot products of each matrix row and the column vector.
Result[] := DotProduct(@row[], column);
Result[] := DotProduct(@row[], column);
Result[] := DotProduct(@row[], column);
Result[] := DotProduct(@row[], column); // Copy temporary result to original column.
column^[] := Result[];
column^[] := Result[];
column^[] := Result[];
column^[] := Result[];
end; procedure MixColumns(state: PByteArray);
begin
MixColumn(@state[ * ]);
MixColumn(@state[ * ]);
MixColumn(@state[ * ]);
MixColumn(@state[ * ]);
end; procedure ShiftRows(state: PByteArray);
var
temp: Byte;
begin
// Note: State is arranged column by column. // Cycle second row left one time.
temp := state^[ + * ];
state^[ + * ] := state^[ + * ];
state^[ + * ] := state^[ + * ];
state^[ + * ] := state^[ + * ];
state^[ + * ] := temp; // Cycle third row left two times.
temp := state^[ + * ];
state^[ + * ] := state^[ + * ];
state^[ + * ] := temp;
temp := state^[ + * ];
state^[ + * ] := state^[ + * ];
state^[ + * ] := temp; // Cycle fourth row left three times, ie. right once.
temp := state^[ + * ];
state^[ + * ] := state^[ + * ];
state^[ + * ] := state^[ + * ];
state^[ + * ] := state^[ + * ];
state^[ + * ] := temp;
end; procedure Cipher(block, expandedKey: PByteArray);
var
round: Byte;
begin
round := ROUNDS - ;
XORBytes(block, expandedKey, );
Inc(PByte(expandedKey), BLOCKSIZE); repeat
SubBytes(block, );
ShiftRows(block);
MixColumns(block);
XORBytes(block, expandedKey, );
Inc(PByte(expandedKey), BLOCKSIZE);
round := round - ;
until (round = ); SubBytes(block, );
ShiftRows(block);
XORBytes(block, expandedKey, );
end; procedure aesEncInit;
var
i: Integer;
begin
powTbl := @block1;
logTbl := @tempbuf;
CalcPowLog(powTbl, logTbl); sBox := @block2;
CalcSBox(sBox); expandedKey := @block1;
KeyExpansion(expandedKey);
end; procedure aesEncrypt(buffer, chainBlock: PByteArray);
begin
XORBytes(buffer, chainBlock, BLOCKSIZE);
Cipher(buffer, expandedKey);
CopyBytes(chainBlock, buffer, BLOCKSIZE);
end; end.

自带了 Base64 编解

procedure EncodeStream(Input, Output: TStream);
procedure DecodeStream(Input, Output: TStream);
function EncodeString(const Input: string): string;
function DecodeString(const Input: string): string;
{********************************************************}
{ }
{ Borland Delphi Visual Component Library }
{ }
{ Copyright (c) 2000, 2001 Borland Software Corporation }
{ }
{********************************************************}
unit EncdDecd;
{ Have string use stream encoding since that logic wraps properly }
interface
uses Classes;
procedure EncodeStream(Input, Output: TStream);
procedure DecodeStream(Input, Output: TStream);
function EncodeString(const Input: string): string;
function DecodeString(const Input: string): string;
implementation
const
EncodeTable: array[..] of Char ='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +'abcdefghijklmnopqrstuvwxyz' +'0123456789+/';
DecodeTable: array[#..#] of Integer = (Byte('='), , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , );
type
PPacket = ^TPacket;
TPacket = packed record
case Integer of
: (b0, b1, b2, b3: Byte);
: (i: Integer);
: (a: array[..] of Byte);
: (c: array[..] of Char);
end;
procedure EncodePacket(const Packet: TPacket; NumChars: Integer; OutBuf: PChar);
begin
OutBuf[] := EnCodeTable[Packet.a[] shr ];
OutBuf[] := EnCodeTable[((Packet.a[] shl ) or (Packet.a[] shr )) and $0000003f];
if NumChars < then
OutBuf[] := '='
else
OutBuf[] := EnCodeTable[((Packet.a[] shl ) or (Packet.a[] shr )) and $0000003f];
if NumChars < then
OutBuf[] := '='
else
OutBuf[] := EnCodeTable[Packet.a[] and $0000003f];
end;
function DecodePacket(InBuf: PChar; var nChars: Integer): TPacket;
begin
Result.a[] := (DecodeTable[InBuf[]] shl ) or (DecodeTable[InBuf[]] shr );
NChars := ;
if InBuf[] <> '=' then
begin
Inc(NChars);
Result.a[] := Byte((DecodeTable[InBuf[]] shl ) or (DecodeTable[InBuf[]] shr ));
end;
if InBuf[] <> '=' then
begin
Inc(NChars);
Result.a[] := Byte((DecodeTable[InBuf[]] shl ) or DecodeTable[InBuf[]]);
end;
end;
procedure EncodeStream(Input, Output: TStream);
type
PInteger = ^Integer;
var
InBuf: array[..] of Byte;
OutBuf: array[..] of Char;
BufPtr: PChar;
I, J, K, BytesRead: Integer;
Packet: TPacket;
begin
K := ;
repeat
BytesRead := Input.Read(InBuf, SizeOf(InBuf));
I := ;
BufPtr := OutBuf;
while I < BytesRead do
begin
if BytesRead - I < then
J := BytesRead - I
else
J := ;
Packet.i := ;
Packet.b0 := InBuf[I];
if J > then
Packet.b1 := InBuf[I + ]; if J > then
Packet.b2 := InBuf[I + ];
EncodePacket(Packet, J, BufPtr);
Inc(I, );
Inc(BufPtr, );
Inc(K, ); if K > then
begin
BufPtr[] := #$0D;
BufPtr[] := #$0A;
Inc(BufPtr, );
K := ;
end;
end;
Output.Write(Outbuf, BufPtr - PChar(@OutBuf));
until
BytesRead = ;
end;
procedure DecodeStream(Input, Output: TStream);
var
InBuf: array[..] of Char;
OutBuf: array[..] of Byte;
InBufPtr, OutBufPtr: PChar;
I, J, K, BytesRead: Integer;
Packet: TPacket;
procedure SkipWhite;
var
C: Char;
NumRead: Integer;
begin
while True do
begin
NumRead := Input.Read(C, );
if NumRead = then
begin
if C in [''..'','A'..'Z','a'..'z','+','/','='] then
begin
Input.Position := Input.Position - ;
Break;
end;
end
else
Break;
end;
end;
function ReadInput: Integer;
var
WhiteFound, EndReached : Boolean;
CntRead, Idx, IdxEnd: Integer;
begin
IdxEnd:= ;
repeat
WhiteFound := False;
CntRead := Input.Read(InBuf[IdxEnd], (SizeOf(InBuf)-IdxEnd));
EndReached := CntRead < (SizeOf(InBuf)-IdxEnd);
Idx := IdxEnd;
IdxEnd := CntRead + IdxEnd;
while (Idx < IdxEnd) do
begin
if not (InBuf[Idx] in [''..'','A'..'Z','a'..'z','+','/','=']) then
begin
Dec(IdxEnd);
if Idx < IdxEnd then
Move(InBuf[Idx+], InBuf[Idx], IdxEnd-Idx);
WhiteFound := True;
end
else
Inc(Idx);
end;
until (not WhiteFound) or (EndReached);
Result := IdxEnd;
end;
begin
repeat
SkipWhite;
{BytesRead := Input.Read(InBuf, SizeOf(InBuf)); }
BytesRead := ReadInput;
InBufPtr := InBuf;
OutBufPtr := @OutBuf;
I := ;
while I < BytesRead do
begin
Packet := DecodePacket(InBufPtr, J);
K := ;
while J > do
begin
OutBufPtr^ := Char(Packet.a[K]);
Inc(OutBufPtr);
Dec(J);
Inc(K);
end;
Inc(InBufPtr, );
Inc(I, );
end;
Output.Write(OutBuf, OutBufPtr - PChar(@OutBuf));
until BytesRead = ;
end;
function EncodeString(const Input: string): string;
var
InStr, OutStr: TStringStream;
begin
InStr := TStringStream.Create(Input);
try
OutStr := TStringStream.Create('');
try
EncodeStream(InStr, OutStr);
Result := OutStr.DataString;
finally
OutStr.Free;
end;
finally
InStr.Free;
end;
end;
function DecodeString(const Input: string): string;
var
InStr, OutStr: TStringStream;
begin
InStr := TStringStream.Create(Input);
try
OutStr := TStringStream.Create('');
try
DecodeStream(InStr, OutStr);
Result := OutStr.DataString;
finally
OutStr.Free;
end;
finally
InStr.Free;
end;
end;
end.

Delphi 一些pas的更多相关文章

  1. delphi EncdDecd.pas单元中Encoding方法出现#$D#$A的解决方法

    例如: s:= 'http://detail.tmall.com/item.htm?id=45545826531&abbucket=_AB-M129_B17&acm=03130.100 ...

  2. 问题-[Delphi]MainFrame.pas(4340): E2036 Variable required

    问题现象:写了一个TObjectList的Sort方法,但是写成ObjectList.Sort(@SortBridgeEDOReportQtys); 再F9时提示“E2036 Variable req ...

  3. DELPHI与C#语法比较

    1.我做了三年的.NET,也是三个月前因为项目需要转的delphi整个过渡差不多要一周到两周.正常情况两周后就能熟悉delphi.delphi可以调整开发环境的,你把他的属性和解决方案窗口调成和你用V ...

  4. Delphi 制作自定义数据感知控件并装入包(dpk文件)中(与DBText类似的数据感知控件)

    一.基础知识简介: 1.包的命名介绍: 包的命名没有规则,但是建议遵守包的命名约定:包的命名与包的版本相关,包的名称前面几个字符通常表示作者或公司名,也可以是控件的一个描述词,后面紧跟的Std表示运行 ...

  5. initialization & finalization

    Delphi 的pas文件中可以有initialization和finalization两个关键字, 1.initialization关键字: 在initialization关键字到finalizat ...

  6. DelphiTXT文档编辑器

    EXE:http://files.cnblogs.com/xe2011/Text_EditorRelease2013-12-20-185320.rar Delphi XE5 PAS:http://fi ...

  7. [C++学习历程]Visual Studio 2010 的HelloWorld

    大学时期曾学过C++的知识,那时候也没有使用VS这样高档的IDE工具,就是C++6.0那样来的.对于重新拾起C++来说,换了个IDE,那么就先从使用IDE学起吧~ 作者:苏生米沿 本文链接:http: ...

  8. superobject

    GITHUB: https://github.com/hgourvest/superobject # SuperObject ## What is JSON ? - JSON (JavaScript ...

  9. Nginx(三):Linux环境(Ubuntu)下Nginx的安装

    Nginx 是一位俄罗斯人 Igor Sysoev(伊戈尔·塞索斯夫)编写的一款高性能HTTP和反向代理服务器. Nginx 主要是有C编写的,安装Nginx需要GCC编译器(GNU Compiler ...

随机推荐

  1. 防火墙---CentOS

    1.查看防火墙状态 firewall-cmd --state 2.停止防火墙 systemctl stop firewalld.service 3.禁止开机启动防火墙 systemctl disabl ...

  2. MySQL - primary key PK unique key,key PK index

    primary key PK unique key 总结 primary key = unique + not null 主键不能为空每个字段值都不重复,unique可以为空,非空字段不重复 uniq ...

  3. AJAX(包括跨域)post请求封装

    function ajaxPost(dataUrl, parameter, callback, bef_callback, com_callback, err_callback) { $.ajax({ ...

  4. 高级运维(二):搭建Nginx服务器、用户认证、基于域名的虚拟主机、SSL虚拟主机、Nginx反向代理

    一.搭建Nginx服务器 目标: 在IP地址为192.168.4.5的主机上安装部署Nginx服务,并可以将Nginx服务器,要求编译时启用如下功能: 1> SSL加密功能 2> 设置Ng ...

  5. (转)OpenFire源码学习之十二:HttpBind&Script Syntax

    转:http://blog.csdn.net/huwenfeng_2011/article/details/43417343 HttpSessionManager 该类管理所有通过httpbing连接 ...

  6. Linux权限简析

  7. 戏说 .NET GDI+系列学习教程(三、Graphics类的应用_验证码扩展)

    从别人那拷贝的 #region 定义和初始化配置字段 //用户存取验证码字符串 public string validationCode = String.Empty; //生成的验证码字符串 pub ...

  8. input checkbox 禁止选中/修改

    input checkbox 禁止选中 <input type="checkbox"  onclick="return false;" /> inp ...

  9. 7. Jmeter-逻辑控制器介绍与使用

    逻辑控制器介绍与使用 如果(if)控制器 事物控制器 循环控制器 while controller critical section controller foreach控制器 include con ...

  10. SDUTOJ 2498 数据结构实验之图论十一:AOE网上的关键路径

    题目链接:http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Index/problemdetail/pid/2498.html 题目大意 略. 分析 ...