Fixed up WINSCW DEF files for pcre, supressed some warnings when building it.
// sudo.cpp// // Copyright (c) 2008 - 2010 Accenture. All rights reserved.// This component and the accompanying materials are made available// under the terms of the "Eclipse Public License v1.0"// which accompanies this distribution, and is available// at the URL "http://www.eclipse.org/legal/epl-v10.html".// // Initial Contributors:// Accenture - Initial contribution//#define __INCLUDE_CAPABILITY_NAMES__#include <fshell/ioutils.h>#include <f32image.h>#include <fshell/memoryaccesscmd.h>#include <e32rom.h>using namespace IoUtils;class CCmdSudo : public CMemoryAccessCommandBase {public: static CCommandBase* NewLC(); ~CCmdSudo();private: CCmdSudo(); static void DeleteModifiedBinary(TAny* aSelf); void DeleteModifiedBinary(); TBool FileExists(const TDesC& aFileName); void FixupExeInMemoryL(RProcess& aProcess); void CalculateCaps(); void FindExeL(); void CopyExeLC(); void FixupExeL(); void RunExeL(); void FixupCoreExeLC();private: // From CCommandBase. virtual const TDesC& Name() const; virtual void DoRunL(); virtual void ArgumentsL(RCommandArgumentList& aArguments); virtual void OptionsL(RCommandOptionList& aOptions);private: HBufC* iCmd; HBufC* iArgs; RPointerArray<HBufC> iAdd; RPointerArray<HBufC> iRemove; TCapabilitySet iCapsToAdd; TCapabilitySet iCapsToRemove; TUint iSid; TUint iVid; TUint iHeapMin; TUint iHeapMax; TUint iStackSize; TInt iProcessPriority; TBool iKeep; TBool iWait; TBool iChangeBinaryOnDisk; TBool iFileIsInCore; TFileName iPath; TFileName iNewPath; CArrayPtrFlat<HBufC>* iPathsToCleanup; // following 2 are temporaries needed during CopyExeLC TFileName iTempSrc; TFileName iTempDest; };CCommandBase* CCmdSudo::NewLC() { CCmdSudo* self = new(ELeave) CCmdSudo(); CleanupStack::PushL(self); self->BaseConstructL(); return self; }CCmdSudo::~CCmdSudo() { delete iCmd; delete iArgs; iAdd.ResetAndDestroy(); iRemove.ResetAndDestroy(); if (iPathsToCleanup) { for (TInt i = 0; i < iPathsToCleanup->Count(); i++) { HBufC* file = (*iPathsToCleanup)[i]; //Printf(_L("Deleting file %S (not really)\n"), file); Fs().Delete(*file); delete file; } } delete iPathsToCleanup; }CCmdSudo::CCmdSudo() { }TCapability CapabilityFromString(const TDesC& aName) { TBuf<32> cap; for (TInt i = 0; i < ECapability_Limit; i++) { cap.Copy(TPtrC8((TUint8*)CapabilityNames[i])); if (aName.CompareF(cap) == 0) { return (TCapability)i; } } return ECapability_None; }void CCmdSudo::DoRunL() { iPathsToCleanup = new(ELeave) CArrayPtrFlat<HBufC>(8); CalculateCaps(); FindExeL(); if (iChangeBinaryOnDisk) {#ifndef __WINS__ // Don't try and use IsFileInRom on WINSCW, the emulator makes a mess of it and anyway, shadowing isn't supported so it being in the core is irrelevant iFileIsInCore = FsL().IsFileInRom(iPath) != NULL;#endif if (iFileIsInCore) { // Things in core have to be handled differently iNewPath = iPath; // We don't call CopyExeLC so something has to set this FixupCoreExeLC(); } else { CopyExeLC(); FixupExeL(); } } else { if (iHeapMin || iHeapMax || iStackSize) LeaveIfErr(KErrArgument, _L("Heap or stack sizes cannot be modified unless you specify --disk")); if (iKeep) LeaveIfErr(KErrArgument, _L("--keep option makes no sense if --disk isn't specified.")); CleanupStack::PushL((CBase*)NULL); // RunExeL expects a cleanup item for DeleteModifiedBinary, which isn't necessary when --disk isn't specified // Everything else is taken care of from RunExeL } RunExeL(); }void CCmdSudo::FindExeL() { if (!iChangeBinaryOnDisk) { // If we're not changing on disk, it's fine to just use the path as-is and let RProcess::Create sort it out iPath = *iCmd; iNewPath = iPath; return; }#ifdef __WINS__ PrintWarning(_L("On WINS, exe-name must be a complete path to a E32 exe")); iPath = *iCmd;#else // We can't reliably use RProcess::Create then FileName because the reason we're calling sudo may be because // the capabilities don't allow it to load. _LIT(KExe, ".exe"); _LIT(KSysBin, "\\sys\\bin\\"); iPath = *iCmd; if (iPath.Right(KExe().Length()).CompareF(KExe) != 0) { iPath.Append(KExe); } TParsePtrC parse(iPath); if (!parse.PathPresent()) { TFindFile find(FsL()); TInt found = find.FindByDir(iPath, KSysBin); LeaveIfErr(found, _L("Couldn't locate file %S"), &iPath); iPath = find.File(); }#endif }void CCmdSudo::CopyExeLC() { iNewPath = iPath; iNewPath[0] = 'c'; // Has to be on C otherwise the loader performs hash checks iNewPath.Append(_L(".sudoed.exe")); CleanupStack::PushL(TCleanupItem(&CCmdSudo::DeleteModifiedBinary, this)); TInt err = FsL().MkDirAll(iNewPath); // In case C:\sys\bin doesn't exist yet if (err && err != KErrAlreadyExists) { LeaveIfErr(err, _L("Couldn't create C:\\sys\\bin")); } CFileMan* fm = CFileMan::NewL(Fs()); CleanupStack::PushL(fm); LeaveIfErr(fm->Copy(iPath, iNewPath), _L("Couldn't copy file from %S to %S"), &iPath, &iNewPath); // Clear the read-only bit in the case where we've copied from Z drive LeaveIfErr(Fs().SetAtt(iNewPath, 0, KEntryAttReadOnly), _L("Couldn't unset read-only flag")); /* TODO this code looks like it should work but doesn't. Something in cone or similar is not behaving the way it looks like it should. // In case it's an app which will rely on having its main rsc and its mbm file on the same drive as it, copy them over too // (Damn cone for not searching drives or working relative to the reg rsc...) TParsePtrC parse(iPath); TPtrC exename = parse.Name(); _LIT(KResFmt, "%c:\\Resource\\Apps\\%S.rsc"); _LIT(KResDestFmt, "C:\\Resource\\Apps\\%S.sudoed.rsc"); iTempSrc.Format(KResFmt, iPath[0], &exename); iTempDest.Format(KResDestFmt, &exename); iPathsToCleanup->SetReserveL(iPathsToCleanup->Count() + 2); iPathsToCleanup->AppendL(iTempDest.AllocL()); LeaveIfErr(fm->Copy(iTempSrc, iTempDest), _L("Couldn't copy ancillary file %S to %S"), &iTempSrc, &iTempDest); LeaveIfErr(Fs().SetAtt(iTempDest, 0, KEntryAttReadOnly), _L("Couldn't unset read-only flag of %S"), &iTempDest); _LIT(KMbmFmt, "%c:\\Resource\\Apps\\%S.mbm"); iTempSrc.Format(KMbmFmt, iPath[0], &exename); iTempDest.Format(KMbmFmt, 'c', &exename); if (!FileExists(iTempDest)) { iPathsToCleanup->AppendL(iTempDest.AllocL()); LeaveIfErr(fm->Copy(iTempSrc, iTempDest), _L("Couldn't copy ancillary file %S to %S"), &iTempSrc, &iTempDest); LeaveIfErr(Fs().SetAtt(iTempDest, 0, KEntryAttReadOnly), _L("Couldn't unset read-only flag of %S"), &iTempDest); } */ CleanupStack::PopAndDestroy(fm); }void CCmdSudo::FixupExeL() { // Now fix up the capabilities or other stuff RFile file; CleanupClosePushL(file); LeaveIfErr(file.Open(Fs(), iNewPath, EFileWrite|EFileStream|EFileShareAny), _L("Couldn't open file")); E32ImageHeaderV* imageHeader=new(ELeave)E32ImageHeaderV; CleanupStack::PushL(imageHeader); TPckg<E32ImageHeaderV> ptr(*imageHeader); LeaveIfErr(file.Read(ptr, sizeof(E32ImageHeaderV)), _L("Couldn't read E32ImageHeader")); SSecurityInfo& secinfo = imageHeader->iS; for (TInt i = 0; i < ECapability_Limit; i++) { TCapability cap = (TCapability)i; if (iCapsToAdd.HasCapability(cap)) secinfo.iCaps.AddCapability(cap); if (iCapsToRemove.HasCapability(cap)) reinterpret_cast<TCapabilitySet*>(&secinfo.iCaps)->RemoveCapability(cap); } if (iOptions.IsPresent(&iSid)) { secinfo.iSecureId = iSid; } if (iOptions.IsPresent(&iVid)) { secinfo.iVendorId = iVid; } if (iHeapMin) { imageHeader->iHeapSizeMin = iHeapMin; } if (iHeapMax) { imageHeader->iHeapSizeMax = iHeapMax; } if (iStackSize) { imageHeader->iStackSize = iStackSize; } if (iProcessPriority) { imageHeader->iProcessPriority = iProcessPriority; } // Update e32 checksum imageHeader->iHeaderCrc = KImageCrcInitialiser; TUint32 crc = 0; Mem::Crc32(crc, imageHeader, imageHeader->TotalSize()); imageHeader->iHeaderCrc = crc; LeaveIfErr(file.Write(0, ptr), _L("Couldn't write updated header back to file")); CleanupStack::PopAndDestroy(2, &file); // imageHeader, file }void CCmdSudo::RunExeL() { // Now actually execute it#ifdef __WINS__ if (iChangeBinaryOnDisk) { PrintWarning(_L("Updated file written to %S. Not actually executing it."), &iNewPath); CleanupStack::Pop(); // DeleteModifiedBinary return; }#endif RChildProcess childProcess; TRAPL(childProcess.CreateL(iNewPath, iArgs ? *iArgs : KNullDesC(), IoSession(), Stdin(), Stdout(), Stderr(), Env()), _L("Failed to execute %S"), &iNewPath); if (iKeep) { Printf(_L("Executing %S...\r\n"), &iNewPath); CleanupStack::Pop(); // Don't delete if user asked for --keep } else { CleanupStack::PopAndDestroy(); // DeleteModifiedBinary - remove the binary before we actually start running it, so it is guaranteed cleaned up even if the user kills us with ctrl-c } if (!iChangeBinaryOnDisk) { // Time to get memaccess involved TRAPD(err, FixupExeInMemoryL(childProcess.Process())); if (err) { childProcess.Process().Kill(err); childProcess.Close(); User::Leave(err); } } if (iWait) { Printf(_L("Process is created but not yet resumed. Press a key to continue...\r\n")); Stdin().ReadKey(); } TRequestStatus stat; childProcess.Run(stat); User::WaitForRequest(stat); TInt err = stat.Int(); childProcess.Close(); User::LeaveIfError(err); // This gets translated to our exe's return code I hope }const TDesC& CCmdSudo::Name() const { _LIT(KName, "sudo"); return KName; }void CCmdSudo::ArgumentsL(RCommandArgumentList& aArguments) { aArguments.AppendStringL(iCmd, _L("exe-name")); aArguments.AppendStringL(iArgs, _L("arguments")); }void CCmdSudo::OptionsL(RCommandOptionList& aOptions) { aOptions.AppendStringL(iAdd, _L("add-cap")); aOptions.AppendStringL(iRemove, _L("remove-cap")); aOptions.AppendUintL(iSid, _L("sid")); aOptions.AppendUintL(iVid, _L("vid")); aOptions.AppendUintL(iHeapMin, _L("heap-min")); aOptions.AppendUintL(iHeapMax, _L("heap-max")); aOptions.AppendUintL(iStackSize, _L("stack-size")); aOptions.AppendIntL(iProcessPriority, _L("process-priority")); aOptions.AppendBoolL(iKeep, _L("keep")); aOptions.AppendBoolL(iChangeBinaryOnDisk, _L("disk")); aOptions.AppendBoolL(iWait, _L("wait")); }void CCmdSudo::DeleteModifiedBinary(TAny* aSelf) { CCmdSudo* self = static_cast<CCmdSudo*>(aSelf); self->DeleteModifiedBinary(); }void CCmdSudo::DeleteModifiedBinary() { if (iFileIsInCore) {#ifdef FSHELL_MEMORY_ACCESS_SUPPORT iMemAccess.FreeShadowMemory((TLinAddr)Fs().IsFileInRom(iPath), sizeof(TRomImageHeader));#endif } else { TInt err = Fs().Delete(iNewPath); if (err && err != KErrNotFound && err != KErrPathNotFound) PrintError(err, _L("Couldn't delete file %S"), &iNewPath); } }EXE_BOILER_PLATE(CCmdSudo)TBool CCmdSudo::FileExists(const TDesC& aFileName) { TEntry entry; return Fs().Entry(aFileName, entry) == KErrNone; }void CCmdSudo::FixupExeInMemoryL(RProcess& aProcess) {#ifdef FSHELL_MEMORY_ACCESS_SUPPORT LoadMemoryAccessL(); TProcessProperties prop; prop.iCapsToAdd = iCapsToAdd; prop.iCapsToRemove = iCapsToRemove; prop.iProcessPriority = iProcessPriority; if (iOptions.IsPresent(&iSid)) { prop.iSid = iSid; } if (iOptions.IsPresent(&iVid)) { prop.iVid = iVid; } LeaveIfErr(iMemAccess.SetProcessProperties(aProcess, prop), _L("Couldn't set process properties using memoryaccess"));#else (void)aProcess; LeaveIfErr(KErrNotSupported, _L("Can't fixup process in memory without MemoryAccess, try the --disk option instead"));#endif }void CCmdSudo::CalculateCaps() { _LIT(KAll, "All"); // Add caps iCapsToAdd.SetEmpty(); for (TInt i = 0; i < iAdd.Count(); i++) { const TDesC& capName = *iAdd[i]; TCapability cap = CapabilityFromString(capName); if (cap == ECapability_None) { if (capName.CompareF(KAll) == 0) { // The pseudo-cap 'All' iCapsToAdd.SetAllSupported(); } else { PrintWarning(_L("Couldn't understand capability name %S"), &capName); } } else { iCapsToAdd.AddCapability(cap); } } // Remove caps iCapsToRemove.SetEmpty(); for (TInt i = 0; i < iRemove.Count(); i++) { const TDesC& capName = *iRemove[i]; TCapability cap = CapabilityFromString(capName); if (cap == ECapability_None) { if (capName.CompareF(KAll) == 0) { // The pseudo-cap 'All' iCapsToRemove.SetAllSupported(); } else { PrintWarning(_L("Couldn't understand capability name %S"), &capName); } } else { iCapsToRemove.AddCapability(cap); } } TBool noOptions = (iAdd.Count() == 0) && (iRemove.Count() == 0) && !iOptions.IsPresent(&iSid) && !iOptions.IsPresent(&iVid) && (iHeapMin == 0) && (iHeapMax == 0) && (iStackSize == 0) && (iProcessPriority == 0); if (noOptions) { // Default to All -TCB iCapsToAdd.SetAllSupported(); iCapsToRemove.AddCapability(ECapabilityTCB); } }void CCmdSudo::FixupCoreExeLC() {#ifdef FSHELL_MEMORY_ACCESS_SUPPORT LoadMemoryAccessL(); const TRomImageHeader* imageHeader = (const TRomImageHeader*)FsL().IsFileInRom(iPath); if (!imageHeader) LeaveIfErr(KErrNotFound, _L("In FixupCoreExeLC but IsFileInRom returned null??")); SCapabilitySet caps = imageHeader->iS.iCaps; for (TInt i = 0; i < ECapability_Limit; i++) { TCapability cap = (TCapability)i; if (iCapsToAdd.HasCapability(cap)) caps.AddCapability(cap); if (iCapsToRemove.HasCapability(cap)) reinterpret_cast<TCapabilitySet*>(&caps)->RemoveCapability(cap); } TPckg<SCapabilitySet> pkg(caps); LeaveIfErr(iMemAccess.WriteShadowMemory((TLinAddr)&imageHeader->iS.iCaps, pkg), _L("Couldn't write shadow memory for caps")); if (iOptions.IsPresent(&iSid)) { TPckg<TUint> pkg(iSid); LeaveIfErr(iMemAccess.WriteShadowMemory((TLinAddr)&imageHeader->iS.iSecureId, pkg), _L("Couldn't write shadow memory for sid")); } if (iOptions.IsPresent(&iVid)) { TPckg<TUint> pkg(iVid); LeaveIfErr(iMemAccess.WriteShadowMemory((TLinAddr)&imageHeader->iS.iVendorId, pkg), _L("Couldn't write shadow memory for sid")); } if (iHeapMin) { TPckg<TUint> pkg(iHeapMin); LeaveIfErr(iMemAccess.WriteShadowMemory((TLinAddr)&imageHeader->iHeapSizeMin, pkg), _L("Couldn't write shadow memory for iHeapSizeMin")); } if (iHeapMax) { TPckg<TUint> pkg(iHeapMax); LeaveIfErr(iMemAccess.WriteShadowMemory((TLinAddr)&imageHeader->iHeapSizeMax, pkg), _L("Couldn't write shadow memory for iHeapSizeMax")); } if (iStackSize) { TPckg<TUint> pkg(iStackSize); LeaveIfErr(iMemAccess.WriteShadowMemory((TLinAddr)&imageHeader->iStackSize, pkg), _L("Couldn't write shadow memory for iStackSize")); } if (iProcessPriority) { TPckg<TUint> pkg(iProcessPriority); LeaveIfErr(iMemAccess.WriteShadowMemory((TLinAddr)&imageHeader->iPriority, pkg), _L("Couldn't write shadow memory for iProcessPriority")); } // DeleteModifiedBinary does the right thing in the case of shadowing CleanupStack::PushL(TCleanupItem(&CCmdSudo::DeleteModifiedBinary, this));#else LeaveIfErr(KErrNotSupported, _L("Can't fixup an exe in Core image without memoryaccess"));#endif }