IsolatedStorage.GetFileNames fails on MonoTouch/MonoDroid - c#-4.0

I was trying out MonoTouch/MonoAndroid and everything was going
well until I called IsolatedStorageFile.GetFileNames(string) function. The
parameter was "Foo/Foo1/*". The result is SecurityException with no message.
The directory "Foo/Foo1" exists, because it has just been found using IsolatedStorageFile.GetDirectoryNames() call.
I identified this bit in Mono sources that throws the exception (in IsolatedStorageFile.cs):
DirectoryInfo[] subdirs = directory.GetDirectories (path);
// we're looking for a single result, identical to path (no pattern here)
// we're also looking for something under the current path (not
outside isolated storage)
if ((subdirs.Length == 1) && (subdirs [0].Name == path) && (subdirs[0].FullName.IndexOf(directory.FullName) >= 0)) {
afi = subdirs [0].GetFiles (pattern);
} else {
// CAS, even in FullTrust, normally enforce IsolatedStorage
throw new SecurityException ();
}
I can't step into it with the debugger so I don't know why the
condition is false. This happens both on iOS and Android. There was a
similar issue logged long time ago at
http://www.digipedia.pl/usenet/thread/12492/1724/#post1724, but there
are no replies.
The same code works on Windows Phone 7 without problems (with \ for path separators).
Has anyone got any ideas what might be causing it? Is it the uppercase in
directory names a problem?

It is a bug in Mono. IsolatedStorage will not work with paths that contain more than one directory in a row (such as Foo/Foo1/*)
I copied the code of GetFileNames() method from Mono to my project so that I can debug it. I found out that the problem is in the 2nd term of this condition (IsolatedStorageFile.cs:846):
if ((subdirs.Length == 1) && (subdirs [0].Name == path) &&(subdirs[0].FullName.IndexOf(directory.FullName) >= 0)) {
afi = subdirs [0].GetFiles (pattern);
} else {
// CAS, even in FullTrust, normally enforce IsolatedStorage
throw new SecurityException ();
}
For example when path passed to GetFileNames() is "Foo/Bar/*", subdirs[0].Name will be "Bar" while path will be "Foo/Bar" and the condition will fail causing the exception.

Related

Can you use Detours in an exe?

I want to replace the LoadLibrary functions to prevent the loading of blacklisted dlls that might be injected.
I copied the sample code from _win32.cpp for the LoadLibrary functions I will need. I used LoadLibraryW, LoadLibraryExW, LoadLibraryA and LoadLibraryExA. Only showing one call as they are all the same but the function name.
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
LONG l = DetourDetach(&(PVOID&)Real_LoadLibraryA, Mine_LoadLibraryA);
if (l != 0)
{
__debugbreak();
}
PVOID* ppbFailedPointer = nullptr;
LONG error = DetourTransactionCommitEx(&ppbFailedPointer);
if (error != 0)
{
__debugbreak();
}
DetourDetach always returns ERROR_INVALID_BLOCK.
I can run the samples fine, but they are all examples of injecting code using a dll.
Thanks, anyone for looking, it was my stupid mistake. I called DetourDetach when I should have been calling DetourAttach.
I have it working now.

EPPlus multiplying a range by a constant inside a VLookup function returning ValueError

I am using the EPPlus library in my ASP.Net application.
What I am trying to do is open a spreadsheet, input some values into cells and then read another cell which contains the result of a calculation. The spreadsheet itself is confidential so I can't provide many details on it.
In order to get my calculations to work I have had to modify the source code for EPplus, changing the Compile function in the ExcelAddressExpression.cs file to ignore the ParentIsLookupFunction bool as shown at the bottom of the question.
so it was able to evaluate the term 5*$f$7
What I want to know is what situations is it useful to keep the CompileResult as an ExcelAddress, so I do not run into any incorrect calculations or errors in other parts of the spreadsheet.
For reference here are the steps I went though to get here:
My code is something like this
using (ExcelPackage p = new ExcelPackage(FilePath, true))
{
ExcelWorksheet ws = p.Workbook.Worksheets["Calculations"];
ws.Cells["b7"].Value = 50;
ws.Cells["f9"].Value = 500000;
ws.Cells["j216"].Calculate();
string result = ws.Cells["j216"].Value.ToString();
}
The formula in cell J216 is
=VLOOKUP($B$7+$F$221+$K$13-$F$8-1,Sheet2!$A$4:$T$103,5*$F$7+2*$B$8+$B$9-5,FALSE)
and the result I got was '#VALUE!'
I have attached a log file and found the issue is in the VLookup function
Worksheet: Calculations
Address: J216
OfficeOpenXml.FormulaParsing.Exceptions.ExcelErrorValueException: #VALUE!
at OfficeOpenXml.FormulaParsing.Excel.Functions.IntArgumentParser.Parse(Object obj)
at OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup.LookupArguments..ctor(IEnumerable`1 arguments, ArgumentParsers argumentParsers, ParsingContext context)
at OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup.VLookup.Execute(IEnumerable`1 arguments, ParsingContext context)
at OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionCompilers.LookupFunctionCompiler.Compile(IEnumerable`1 children, ParsingContext context)
at OfficeOpenXml.FormulaParsing.ExpressionGraph.FunctionExpression.Compile()
The next step I took was to download the source code for EPPlus, and debug through the code as it executed, eventually finding the problem was at line 165 of Operator.cs
l = l ?? new CompileResult(0, DataType.Integer);
r = r ?? new CompileResult(0, DataType.Integer);
if (l.DataType == DataType.Integer && r.DataType == DataType.Integer)
{
return new CompileResult(l.ResultNumeric*r.ResultNumeric, DataType.Integer);
}
else if ((l.IsNumeric || l.IsNumericString || l.IsDateString || l.Result is ExcelDataProvider.IRangeInfo) &&
(r.IsNumeric || r.IsNumericString || r.IsDateString || r.Result is ExcelDataProvider.IRangeInfo))
{
return new CompileResult(l.ResultNumeric*r.ResultNumeric, DataType.Decimal);
}
return new CompileResult(eErrorType.Value);
When evaluating the equation 5*$F$7, the second parameter was of DataType ExcelAddress which is results in a compile result exception being thrown.
The root cause of this is in the Compile function of the ExcelAddressExpression.cs file the ParentIsLookupFunction boolean controls whether the cell is evaluated or left as an address.
public override CompileResult Compile()
{
if (ParentIsLookupFunction)
{
return new CompileResult(ExpressionString, DataType.ExcelAddress);
}
else
{
return CompileRangeValues();
}
}
I have modified my version of the code to simply be
public override CompileResult Compile()
{
return CompileRangeValues();
}
As said at the top of the question, what I want to know is why would you want to return the ExcelAddress CompileResult, It was obviously put there for a reason and I do not want to break some other calculations in my spreadsheet.
I can confirm though that for at least this calculation it is now working correctly.
I wrote the formula engine of EPPlus some years ago, but don't work much on the project these days. If I recall it correctly there are cases where you don't want to compile the excel address in the expression, but rather pass it on to the executing function. Have you tried to run the unit tests? The formula engine is covered by hundreds of tests and the test result could provide some guidance.
I was able to answer this after experimenting with different spreadsheets.
Returning the value as an ExcelAddress is useful in the event that the address is not operated on like in my earlier example 5*$F$7 such as an IF statement inside a VLookup.
In the event that there is an operator you will want to return the contents of the cell.
I modified the EPPlus code to now check for any operators separating terms in the formula
public override CompileResult Compile()
{
if (ParentIsLookupFunction &&
Operator == null &&
(Prev == null || Prev.Operator == null))
{
return new CompileResult(ExpressionString, DataType.ExcelAddress);
}
else
{
return CompileRangeValues();
}
}

How do I determine the time needed to open the big file (20MB)?

We are working on Universal Windows Apps in which we are opening the files (whose size is 20MB) using below code.
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.FileTypeFilter.Add(".abc");
StorageFile file = await openPicker.PickSingleFileAsync();
if (file == null) return false;
FlowSheetFilePath = file.Path;
LaunchQuerySupportStatus status = await Launcher.QueryFileSupportAsync(file);
if (status == LaunchQuerySupportStatus.Available)
{
bool didLaunch = await Launcher.LaunchFileAsync(file);
if (didLaunch)
{
}
}
In the above code, Is there any way to determine how much time is needed to completely open the file whose size is around 20MB?
It's not possible. Note that this will depend not only on device configuration/type but ola CPU overload and so on.
If your app read/processes the file you may implement some kind of ProgressBar that will indicate how much work is already done (with implementation of IProgress<>) and how much is left, however that also won't help you with determination of time - you can think of estimating the time left basing on that what is already done, but this is only estimation and will surely change over time. But this won't also help you with Launcher.LaunchFileAsync(file).

Freeing a BSTR using ::SysFreeString(). More Platform Dependant?

I am writing a COM Server which have a plenty of Interfaces and methods. And most of the methods have the BSTR as the parameters and as local parameters used for the return. A snippet looks like
Update 5:
The real code. This fetches from bunch of Data based on a specific condition the DB to populate an array of Object.
STDMETHODIMP CApplication::GetAllAddressByName(BSTR bstrParamName, VARIANT *vAdddresses)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
//check the Database server connection
COleSafeArray saAddress;
HRESULT hr;
// Prepare the SQL Strings dan Query the DB
long lRecCount = table.GetRecordCount();
if (lRecCount > 0)
{
//create one dimension safe array for putting details
saAddress.CreateOneDim(VT_DISPATCH,lRecCount);
IAddress *pIAddress = NULL;
//retrieve details
for(long iRet = table.MoveFirst(),iCount=0; !iRet; iRet = table.MoveNext(),iCount++)
{
CComObject<CAddress> *pAddress;
hr = CComObject<CAddress>::CreateInstance(&pAddress);
if (SUCCEEDED(hr))
{
BSTR bstrStreet = ::SysAllocString(table.m_pRecordData->Street);
pAddress->put_StreetName(bstrStreet);
BSTR bstrCity = ::SysAllocString(table.m_pRecordData->City);
pAddress->put_CityName(bstrCity);
}
hr = pAddress->QueryInterface(IID_IAddress, (void**)&pIAddress);
if(SUCCEEDED(hr))
{
saAddress.PutElement(&iCount,pIAddress);
}
}
*vAdddresses=saAddress.Detach();
}
table.Close();
return S_OK;
}
STDMETHODIMP CAddress::put_CityName(BSTR bstrCityName)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// m_sCityName is of CComBSTR Type
m_sCityName.Empty();//free the old string
m_sCityName = ::SysAllocString(bstrCityName);//create the memory for the new string
return S_OK;
}
The problem lies in the Memory Freeing part. The code works very fine in any Win XP machines, but when comes to WIN2K8 R2 and WIN7 the code crashes and pointing to the ::SysFreeString() as the culprit. The MSDN is not adequate to the solution.
Can anyone please help in finding the right solution?
Thanks a lot in advance :)
Update 1:
I have tried using the CComBSTR as per the suggestion in the place of raw BSTR, initialized using direct CString's and excluded the SysFreeString(). But for my trouble, on getting out of scope the system is calling the SysFreeString() which again causes the crash :(
Update 2:
With the same CComBSTR i tried to allocate using the SysAllocString() , the problem remains same :(
Update 3:
I am tired of all the options and in peace I am having only question in mind
Is it necessary to free the BSTR through SysFreeString() which was
allocated using SysAllocString()/string.AllocSysString()?
Update 4:
I missed to provide the information about the crash. When I tried to debug the COM server crashed with a error saying
"Possible Heap Corruption"
. Please help me out of here.. :(
// Now All Things are packed in to the Object
obj.Name = bstrName;
obj.Name2 = bstrname2;
I don't quite understand what do you mean by saying that things are packed since you're just copying pointers to the strings, and at the moment when you call SysFreeString obj.Name and obj.Name2 will point to an invalid block of memory. Although this code is not safe, it looks like if the source of your problem is class CFoo. You should show us more details of your code
I suggest you to use a CComBSTR class which will take a responsibility for releasing the memory.
UPDATE
#include <atlbase.h>
using namespace ATL;
...
{
CComBSTR bstrname(_T("Some Name"));
CComBSTR bstrname2(_T("Another Name"));
// Here one may work with these variables if needed
...
// Copy the local values to the Obj's member Variable
bstrname.Copy(&obj.Name);
bstrname2.Copy(&obj.Name2);
}
UPDATE2
First of all one should free bstrCity and bstrStreetName with SysFreeString or use CComBSTR instead within this block:
if (SUCCEEDED(hr))
{
BSTR bstrStreet = ::SysAllocString(table.m_pRecordData->Street);
pAddress->put_StreetName(bstrStreet);
BSTR bstrCity = ::SysAllocString(table.m_pRecordData->City);
pAddress->put_CityName(bstrCity);
// SysFreeString(bstrStreet)
// SysFreeString(bstrCity)
}
Consider to amplify the loop's condition !iRet with iCount < lRecCount.
for(...; !iRet /* && (iCount < lRecCount) */; ...)
Also, here:
m_sCityName = ::SysAllocString(bstrCityName);
you allocate memory but never release it since internally CComBSTR& operator = (OLESTR ..) allocates a new storage itself. One should rewrite is as follows:
m_sCityName = bstrCityName;
Everything else, looks good for me
UPDATE3
Well, Heap corruption is often a consequence of writing some values outside of the allocated memory block. Say you allocate an array of length 5 and put some value to the 6th position
Finally I have found the real reason for the Heap Corruption that happened in the code.
The put_StreetName/put_CityName of the IAddress/CAddress is designed in a following way.
STDMETHODIMP CAddress::put_CityName(BSTR bstrCityName)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
m_sCityName.Empty();
TrimBSTR(bstrCityName);
m_sCityName = ::SysAllocString(bstrCityName);
return S_OK;
}
BSTR CAddress::TrimBSTR(BSTR bstrString)
{
CString sTmpStr(bstrString);
sTmpStr.TrimLeft();
sTmpStr.TrimRight();
SysReAllocString(&bstrString,sTmpStr); // The Devilish Line
}
The Devilish Line of code is the real culprit that caused the Memory to go hell.
What caused the trouble?
In this line of code, the BSTR string passed as a parameter is from another application and the real memory is in another realm. So the system is trying to reallocate teh string. Either succeed or not, the same is tried to cleared off from the memory in original application/realm, thus causing a crash.
What still unsolved?
Why the same piece of code doesn't crashed a single time in Win XP and
older systems? :(
Thanks for all who took their time to answer and solve my problem :)

How do I avoid this race condition with readdir/inotify?

Suppose I want to invoke some command on all files in a directory and set a watch to invoke that command on all files that get created in that directory. If I do:
while( ( sdi = readdir( d )) != NULL ) { ... }
closedir( d );
/* Files created here will be missed */
inotify_add_watch( ... );
then some files will potentially be missed. If I call inotify_add_watch()
before the readdir(), files may be acted on twice (it would require
a fair bit of infrastructure to prevent acting twice, and it seems that
the edge cases would be difficult to handle). Is there a simple way to avoid
having to record the names of all files worked on during the readdir loop and
comparing those to the names returned in the inotify_event structure? I can
minimize the amount of necessary comparisons with:
while( ( sdi = readdir( d )) != NULL ) { ... }
inotify_add_watch( ... );
while( ( sdi = readdir( d )) != NULL ) { /* record name */ ... }
closedir( d );
And usually the second readdir() loop will do nothing, but this feels like a bad hack.
You simply can't. The more you hack, the more race conditions you'll get.
The simplest actually working solution is to set the watch before using opendir(), and keep a list (set) of already used names (or their hashes).
But this isn't perfect either. User can have the file open in a text editor; you fix it, user saves it and the directory contains unfixed file anyway, though it's on your list.
The best method would be to be able for the program to actually distinguish used files by their content. In other words, you set watch, call command on readdir() results, then call it on inotify results and let the command itself know whether the file is fine already or not.

Resources