From: <Or...@us...> - 2008-06-05 20:07:38
|
Revision: 217 http://acmcontester.svn.sourceforge.net/acmcontester/?rev=217&view=rev Author: Oracle_ Date: 2008-06-05 13:07:26 -0700 (Thu, 05 Jun 2008) Log Message: ----------- Fixed some bugs, added some comments. Modified Paths: -------------- ACMServer/branches/sharp tester/SourceTest/SourceTest.cpp ACMServer/branches/sharp tester/SourceTest/SourceTest.h ACMServer/branches/sharp tester/TestLibrary/TestLibrary.cpp Modified: ACMServer/branches/sharp tester/SourceTest/SourceTest.cpp =================================================================== --- ACMServer/branches/sharp tester/SourceTest/SourceTest.cpp 2008-06-05 14:54:51 UTC (rev 216) +++ ACMServer/branches/sharp tester/SourceTest/SourceTest.cpp 2008-06-05 20:07:26 UTC (rev 217) @@ -8,34 +8,34 @@ #include <Userenv.h> using namespace System::IO; -const wchar_t USER_NAME[]={'T','e','s','t','i','n','g','U','s','e','r'}; -const wchar_t USER_PASSW[]={'U','S','E','R','1','2','3','4','5'}; +const wchar_t USER_NAME[]={'T','e','s','t','i','n','g','U','s','e','r'}; //username for testing +const wchar_t USER_PASSW[]={'U','S','E','R','1','2','3','4','5'}; //password of user for testing namespace SourceTest { -char* StrToArr(String^ str) +char* StrToArr(String^ str) //converts Managed String to C++ string to { return (char*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(str).ToPointer(); } -wchar_t* StrToArrW(String^ str) +wchar_t* StrToArrW(String^ str) //converts Managed String to array of Unicode symbols { return (wchar_t*)System::Runtime::InteropServices::Marshal::StringToHGlobalUni(str).ToPointer(); } -void FreeArr(char* buf) +void FreeArr(char* buf) //destroys C++ string { System::Runtime::InteropServices::Marshal::FreeHGlobal(IntPtr(buf)); } -void FreeArr(wchar_t* buf) +void FreeArr(wchar_t* buf) //destroys array of Unicode symbols { System::Runtime::InteropServices::Marshal::FreeHGlobal(IntPtr(buf)); } -String^ ToStr(int x) +String^ ToStr(int x) //fast convert integer to Managed String { char intg[15]; _itoa_s(x,intg,10); @@ -43,7 +43,7 @@ } -bool FileExists(String^ path) +bool FileExists(String^ path) //checks whether file exists or not { char* buf=StrToArr(path); OFSTRUCT of; @@ -64,7 +64,7 @@ FRunAll=true; lib=LoadLibraryA("TestLibrary.dll"); FSecurity=new TSecure(); -init(); +init(); //initializing of critical section } TSource::~TSource() @@ -72,15 +72,15 @@ if (lib!=NULL) FreeLibrary(lib); delete FSecurity; -final(); +final(); } -void TSource::CheckCL() +void TSource::CheckCL() //checking size of source { try { lock(); - if (lib==NULL) + if (lib==NULL) //no library was found { if (FSrc->Length>FLim.CodeLimit) FCompResult.res=crCL; @@ -102,12 +102,12 @@ } } -void TSource::CheckDF() +void TSource::CheckDF() //checking for DF in source { try { lock(); - if (lib==NULL) + if (lib==NULL) //no library was found { FCompResult.Details+="No checker for DF\n"; } else @@ -127,7 +127,7 @@ } } -void TSource::Compile() +void TSource::Compile() //compiles the source { PROCESS_INFORMATION pi;ZeroMemory(&pi,sizeof(pi)); STARTUPINFO si; ZeroMemory(&si,sizeof(si)); @@ -144,7 +144,7 @@ String^ outpath=gcnew String(FTempPath+"compoutput.txt"); FExePath=FTempPath+"source.exe"; - if (FileExists(FExePath)) + if (FileExists(FExePath)) //delete previsious source { DeleteFile((LPCTSTR)(bufW=StrToArrW(FExePath))); FreeArr(bufW); @@ -194,7 +194,7 @@ ReadFile(oup,compres,size,&len,NULL); CloseHandle(oup); - if (!FileExists(FExePath)) + if (!FileExists(FExePath)) //compilation error { FCompResult.res=crCE; FCompResult.Details+=gcnew String("EXE file not found\n")+gcnew String(compres); @@ -214,7 +214,7 @@ } } -void TSource::RunTests() +void TSource::RunTests() //runs all tests of problem { try { @@ -230,7 +230,7 @@ if (((TResult^)FRes[n-1])->res!=trAC) { FSummary.res->res=((TResult^)FRes[n-1])->res; - if (!FRunAll) break; + if (!FRunAll) break; } n++; } @@ -241,7 +241,7 @@ } } -void TSource::LoadTest(int index,TTest% test) +void TSource::LoadTest(int index,TTest% test) //loads test from file { FILE* inp,*oup,*points; char *bufA; @@ -292,14 +292,14 @@ } } -TCheckAnsRes TSource::CheckAnswer(int index,String^ output) +TCheckAnsRes TSource::CheckAnswer(int index,String^ output) //checks answer for test { try { lock(); TTest t; LoadTest(index,t); - if (lib==NULL) + if (lib==NULL) //lib was not found { if (output!=t.output) return carWA; @@ -318,22 +318,27 @@ } } -void TSource::ProcessAll() +void TSource::ProcessAll() //executes all actions needed to get Summary result for all tests { -CheckCL(); -if (FCompResult.res==crOK) - CheckDF(); else - return ; -if (FCompResult.res==crOK) - Compile(); else - return ; -(*FSummary.compres)=FCompResult; -if (FCompResult.res==crOK) - RunTests(); else - return ; +try +{ + CheckCL(); + if (FCompResult.res==crOK) + CheckDF(); else + return ; + if (FCompResult.res==crOK) + Compile(); else + return ; + if (FCompResult.res==crOK) + RunTests(); else + return ; +} __finally +{ + (*FSummary.compres)=FCompResult; } +} -BOOL DelPrivilege(HANDLE hToken,LPCTSTR lpszPrivilege) +BOOL DelPrivilege(HANDLE hToken,LPCTSTR lpszPrivilege) //deletes privilege from process token { TOKEN_PRIVILEGES tp; LUID luid; @@ -344,16 +349,13 @@ tp.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED; if ( !AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES) NULL,(PDWORD) NULL) ) -{ - int x=GetLastError(); return FALSE; -} if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) return FALSE; return TRUE; } -BOOL AddPrivilege(HANDLE hToken,LPCTSTR lpszPrivilege) +BOOL AddPrivilege(HANDLE hToken,LPCTSTR lpszPrivilege) //adds privilege to process token (in this version unused) { TOKEN_PRIVILEGES tp; LUID luid; @@ -370,7 +372,7 @@ return TRUE; } -void DeletePrivileges(HANDLE proc) +void DeletePrivileges(HANDLE proc) //deletes all privileges from process token { HANDLE hToken; try @@ -417,7 +419,7 @@ } } -void TSource::RunTest(int index) +void TSource::RunTest(int index) //runs one test { PROCESS_INFORMATION pi;ZeroMemory(&pi,sizeof(pi)); STARTUPINFO si;ZeroMemory(&si,sizeof(si)); @@ -462,7 +464,7 @@ SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX); - if (!FSecurity->RunProcess(bufW=StrToArrW(FExePath),TRUE,CREATE_SUSPENDED|CREATE_NO_WINDOW,&si,&pi)) + if (!FSecurity->RunProcess(bufW=StrToArrW(FExePath),TRUE,CREATE_SUSPENDED|CREATE_NO_WINDOW,&si,&pi,it->Details)) { FreeArr(bufW); it->points=0; @@ -470,11 +472,11 @@ if ((err==193)||(err==1455)) { it->res=trRE; - it->Details="Too large array"; + it->Details+=gcnew String("Too large array"); } else { it->res=trIE; - it->Details="Can not start process"; + it->Details+=gcnew String("Can not start process"); } return ; } @@ -503,7 +505,7 @@ { TerminateJobObject(job,0); it->res=trOL; - it->Details="Size of output file excided OutputLimit"; + it->Details+=gcnew String("Size of output file excided OutputLimit"); break; } QueryInformationJobObject(job,JobObjectBasicAccountingInformation,&acc,sizeof(acc),NULL); @@ -513,14 +515,14 @@ { TerminateJobObject(job,0); it->res=trRTL; - it->Details="Real time limit"; + it->Details+=gcnew String("Real time limit"); break; } if ((acc.ThisPeriodTotalKernelTime.QuadPart+acc.ThisPeriodTotalUserTime.QuadPart)>FLim.TimeLimit*10000) { TerminateJobObject(job,0); it->res=trTL; - it->Details="Time Limit"; + it->Details+=gcnew String("Time Limit"); break; } } else @@ -530,7 +532,7 @@ { TerminateJobObject(job,0); it->res=trTL; - it->Details="Time Limit"; + it->Details+=gcnew String("Time Limit"); break; } prc=(TCheckLim)GetProcAddress(lib,"CheckRTL"); @@ -538,7 +540,7 @@ { TerminateJobObject(job,0); it->res=trRTL; - it->Details="Real time Limit"; + it->Details+=gcnew String("Real time Limit"); break; } } @@ -556,18 +558,18 @@ if (code==5) { it->res=trDF; - it->Details="Access denied."; + it->Details+=gcnew String("Access denied."); } else if (code!=0) { it->res=trRE; - it->Details="Runtime error #"+ToStr((int)code); + it->Details+=gcnew String("Runtime error #"+ToStr((int)code)); } needbreak=true; break; case JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT: it->res=trML; - it->Details="Memory Limit"; + it->Details+=gcnew String("Memory Limit"); needbreak=true; break; case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO: @@ -575,12 +577,12 @@ if (code==5) { it->res=trDF; - it->Details="Access denied."; + it->Details+=gcnew String("Access denied."); } else if (code!=0) { it->res=trRE; - it->Details="Runtime error #"+ToStr((int)code); + it->Details+=gcnew String("Runtime error #"+ToStr((int)code)); } needbreak=true; break; @@ -609,7 +611,7 @@ if (!FileExists(oupath)) { it->res=trWA; - it->Details="No output file"; + it->Details+=gcnew String("No output file"); return; } @@ -667,18 +669,23 @@ void TSource::ProcessTest(int index) { -CheckCL(); -if (FCompResult.res==crOK) - CheckDF(); else - return ; -if (FCompResult.res==crOK) - Compile(); else - return ; -(*FSummary.compres)=FCompResult; -if (FCompResult.res==crOK) - RunTest(index); else - return ; +try +{ + CheckCL(); + if (FCompResult.res==crOK) + CheckDF(); else + return ; + if (FCompResult.res==crOK) + Compile(); else + return ; + if (FCompResult.res==crOK) + RunTest(index); else + return ; +} __finally +{ + (*FSummary.compres)=FCompResult; } +} void TSource::LoadLimits() { @@ -759,8 +766,8 @@ TSecure::TSecure() { - SetUserObjectFullAccess( GetThreadDesktop(GetCurrentThreadId())); - SetUserObjectFullAccess( GetProcessWindowStation()); + SetUserObjectFullAccess( GetThreadDesktop(GetCurrentThreadId())); //needed for accessing from CreateProcessAsUser + SetUserObjectFullAccess( GetProcessWindowStation()); //needed for accessing from CreateProcessAsUser USER_INFO_1 ui; NET_API_STATUS st; @@ -771,22 +778,27 @@ ui.usri1_password=(LPWSTR)USER_PASSW; ui.usri1_priv=USER_PRIV_USER; ui.usri1_script_path=NULL; - st=NetUserAdd(NULL,1,(LPBYTE)&ui,NULL); + st=NetUserAdd(NULL,1,(LPBYTE)&ui,NULL); //trying to create new user if (st!=NERR_Success) { if (st==NERR_UserExists) - return; - throw "Can not create user!"; + return; //if user exists just do nothing + MessageBox(NULL,(LPCTSTR)"Can not create testing user - only unsecured mode",(LPCTSTR)"Warning",MB_ICONWARNING|MB_OK); + return; } array<DriveInfo^>^ drv=DriveInfo::GetDrives(); - for (int i=0;i<drv->Length;i++) + for (int i=0;i<drv->Length;i++) //for all drives set limitation if (drv[i]->DriveType==DriveType::Fixed) { - DirectoryInfo^ fi = gcnew DirectoryInfo(drv[i]->Name); - DirectorySecurity^ fs = gcnew DirectorySecurity(drv[i]->Name, AccessControlSections::All); - fs->SetAccessRule(gcnew FileSystemAccessRule("TestingUser",FileSystemRights::FullControl,AccessControlType::Deny)); - fi->SetAccessControl(fs); + DirectoryInfo^ fi = gcnew DirectoryInfo(drv[i]->Name); + DirectorySecurity^ fs = gcnew DirectorySecurity(drv[i]->Name, AccessControlSections::All); + fs->SetAccessRule(gcnew FileSystemAccessRule(gcnew String(USER_NAME),FileSystemRights::FullControl, + InheritanceFlags::ObjectInherit|InheritanceFlags::ContainerInherit, + PropagationFlags::None, + AccessControlType::Deny)); + fi->SetAccessControl(fs); } + } TSecure::~TSecure() @@ -794,11 +806,16 @@ } -bool TSecure::RunProcess(LPWSTR lpCommandLine,BOOL bInheritHandles,DWORD dwCreationFlags,LPSTARTUPINFOW lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation) +bool TSecure::RunProcess(LPWSTR lpCommandLine,BOOL bInheritHandles,DWORD dwCreationFlags,LPSTARTUPINFOW lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation, String^% Details) { HANDLE token=NULL,Token=NULL; wchar_t* env=NULL; if (LogonUser((LPWSTR)USER_NAME,(LPWSTR)".",(LPWSTR)USER_PASSW,LOGON32_LOGON_NETWORK,LOGON32_PROVIDER_DEFAULT,&Token)) + { + FileInfo^ fi=gcnew FileInfo(gcnew String(lpCommandLine)); + FileSecurity^ fs=gcnew FileSecurity(gcnew String(lpCommandLine),AccessControlSections::All); + fs->SetAccessRule(gcnew FileSystemAccessRule(gcnew String(USER_NAME),FileSystemRights::ExecuteFile,AccessControlType::Allow)); + fi->SetAccessControl(fs); if (DuplicateTokenEx(Token,TOKEN_ALL_ACCESS,NULL,SecurityImpersonation,TokenPrimary,&token)) if (ImpersonateLoggedOnUser(token)) if (CreateEnvironmentBlock((LPVOID*)&env,token,FALSE)) @@ -807,9 +824,10 @@ DestroyEnvironmentBlock(env); RevertToSelf(); CloseHandle(token); + Details="Secured process. Result details: "; return true; } - int x=GetLastError(); + } if (env!=NULL) DestroyEnvironmentBlock(env); RevertToSelf(); @@ -817,6 +835,7 @@ CloseHandle(token); if (Token!=NULL) CloseHandle(Token); + Details="Unsecured process. Result details: "; if (CreateProcess(NULL,lpCommandLine,NULL,NULL,bInheritHandles,dwCreationFlags,NULL,NULL,lpStartupInfo,lpProcessInformation)) return true; return false; Modified: ACMServer/branches/sharp tester/SourceTest/SourceTest.h =================================================================== --- ACMServer/branches/sharp tester/SourceTest/SourceTest.h 2008-06-05 14:54:51 UTC (rev 216) +++ ACMServer/branches/sharp tester/SourceTest/SourceTest.h 2008-06-05 20:07:26 UTC (rev 217) @@ -8,14 +8,25 @@ namespace SourceTest { + /* + To normally execute source you need to: + 1. Have privileges SE_ASSIGNPRIMARYTOKEN_NAME and SE_INCREASE_QUOTA_NAME + 2. Have HTFS file system + 3. Have .NET Framework 2.0 or higher + */ + + + ///<summary> + ///TLimits holds information about limits for process + ///</summary> public ref struct TLimits { - int OutputLimit; - int TimeLimit; - int MemoryLimit; - int RealTimeLimit; - int CompilationTimeLimit; - int CodeLimit; + int OutputLimit; //maximum size of output file + int TimeLimit; //maximum kernel time + int MemoryLimit; //maximum virtual memory usage + int RealTimeLimit; //maximum real time + int CompilationTimeLimit; //maximum time for compilation + int CodeLimit; //maximum source size TLimits() { @@ -48,6 +59,9 @@ return value; } }; + ///<summary> + ///TCompRes is all possible results of compilation + ///</summary> public enum TCompRes //result of compilation { @@ -59,6 +73,10 @@ crIE //internal error }; + ///<summary> + ///TRes is all possible results of running the source + ///</summary> + public enum TRes { trAC, //accepted @@ -74,14 +92,18 @@ trOE //output error }; + ///<summary> + ///TResult holds information about results of running the process + ///</summary> + public ref struct TResult { TRes res; - int points; - int UsedMemory; - int UsedTime; - int UsedRealTime; - String^ Details; + int points; //points earned during testing (each test has some points) points are stored in Points.txt (in test folder) + int UsedMemory; //memory peak during testing + int UsedTime; //kernel time used + int UsedRealTime; //real time used + String^ Details; //details of testing TResult() { @@ -115,11 +137,15 @@ } }; + ///<summary> + ///TCompResult holds information about compilation + ///</summary> + public ref struct TCompResult { - TCompRes res; - int UsedTime; - String^ Details; + TCompRes res; //result of compilation + int UsedTime; //time used for compilation + String^ Details; //details of compilation TCompResult(TCompResult% value) { res=value.res; @@ -142,18 +168,23 @@ return value; } }; + ///<summary> + ///TSourceState is all possible states of source during its testing + ///</summary> public enum TSourceState { - ssNone=0, - ssCheckedCL=1, - ssCheckedDF=2, - ssCompiled=3, - ssIsRunning=4, //for multithreading + ssNone=0, //no actions were taken + ssCheckedCL=1, //CodeLimit checked + ssCheckedDF=2, //source is checked for DF + ssCompiled=3, //source is compiled + ssIsRunning=4, //test is running ssTestComplete=5, //next test is gonna be tested ssFinish=6 //all tests is tested }; - + ///<summary> + ///TSummary holds information about total result of processing all tests + ///</summary> public ref struct TSummary { public: @@ -172,12 +203,17 @@ } }; - + ///<summary> + ///TTest holds information about one test + ///</summary> public ref struct TTest { - String^ input,^output; - int points; + String^ input,^output; //input and output of test + int points; //points for test }; + ///<summary> + ///TCheckAnsRes is all possible values, what can give CheckAnswer function from DLL + ///</summary> public enum TCheckAnsRes { @@ -188,12 +224,16 @@ carOE=4 //output error }; + ///<summary> + ///TLang is all possible languages of source (needed for CheckDF) + ///</summary> + public enum TLang { lCpp=0, lPascal=1 }; - + typedef bool (*TCheckSrc)(char* src,int,char*& details); typedef bool (*TCheckLim)(int,int); typedef int (*TCheckAnswer)(char* input, char* output, char* rightoutput); @@ -201,32 +241,39 @@ public delegate void TTestHandler(int index, TResult^ res); + ///<summary> + ///Class that takes part in security - it has to create a user and execute source in his security context + ///</summary> + private class TSecure { private: public: TSecure(); ~TSecure(); - bool RunProcess(LPWSTR lpCommandLine,BOOL bInheritHandles,DWORD dwCreationFlags,LPSTARTUPINFOW lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation); + bool RunProcess(LPWSTR lpCommandLine,BOOL bInheritHandles,DWORD dwCreationFlags,LPSTARTUPINFOW lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation,String^% Details); }; + ///<summary> + ///TSource is main class that incapsulates all information about source and it's testing + ///</summary> public ref class TSource { private: - String^ FSrc; - String^ FExePath; - String^ FProblemPath; - String^ FCompPath; + String^ FSrc; //text of source + String^ FExePath; //executable file + String^ FProblemPath; //path for problem + String^ FCompPath; //path for compiler String^ FTempPath; //this is the place where temporary files will be created - bool FRunAll; - TSourceState FState; - TCompResult FCompResult; - ArrayList FRes; - TSummary FSummary; - TLimits FLim; - TTestHandler^ FTestHandler; - TLang FLang; - TSecure *FSecurity; + bool FRunAll; //if true then all tests will run (no matter on errors) + TSourceState FState; //state of source + TCompResult FCompResult; //result of compilation + ArrayList FRes; //results of each test + TSummary FSummary; //summary results of all tests + TLimits FLim; //limits for testing + TTestHandler^ FTestHandler; //event, that occures when test is completed + TLang FLang; //language of source + TSecure *FSecurity; //security class HMODULE lib; //library that must export: //bool CheckCL(char* src, int cl, char* details) - must check codelimit //bool CheckDF(char* src, int lang, char* details) - must check DF @@ -265,11 +312,11 @@ void CheckDF(); void Compile(); void RunTests(); //all tests - void RunTest(int index); + void RunTest(int index); //only one test TCheckAnsRes CheckAnswer(int index,String^ output); void ProcessAll(); //gets result for all tests void ProcessTest(int index); //gets result for only 1 test - void LoadTest(int index,TTest% test); + void LoadTest(int index,TTest% test); //load test from file void LoadLimits(); //loads limits from a file Limits.txt static String^ TestResultToString(TRes res); static String^ CompileResultToString(TCompRes res); Modified: ACMServer/branches/sharp tester/TestLibrary/TestLibrary.cpp =================================================================== --- ACMServer/branches/sharp tester/TestLibrary/TestLibrary.cpp 2008-06-05 14:54:51 UTC (rev 216) +++ ACMServer/branches/sharp tester/TestLibrary/TestLibrary.cpp 2008-06-05 20:07:26 UTC (rev 217) @@ -14,7 +14,7 @@ TESTLIBRARY_API bool CheckDF(char* src, int lang, char*& details) { details=new char[20]; - strcpy_s(details,20,"CheckDF from DLL"); + strcpy_s(details,20,"CheckDF from DLL\n"); return false; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |