// note: throwing MoonException from here is NOT ok since this code is called async
// and the exception won't be reported, directly, to the caller
void AssemblyGetResponse(IAsyncResult result)
{
Assembly asm;
object[] tuple = (object [])result.AsyncState;
WebRequest wreq = (WebRequest)tuple [0];
ManifestAssemblyKind kind = (ManifestAssemblyKind)tuple [1];
int error_code = (kind == ManifestAssemblyKind.ExternalAssembly) ? 2152 : 2105;
try {
HttpWebResponse wresp = (HttpWebResponse)wreq.EndGetResponse(result);
if (wresp.StatusCode != HttpStatusCode.OK)
{
wresp.Close();
EmitError(error_code, String.Format("Error while downloading the '{0}'.", wreq.RequestUri));
return;
}
if ((kind != ManifestAssemblyKind.ExternalAssembly) && (wresp.ResponseUri != wreq.RequestUri))
{
wresp.Close();
EmitError(error_code, "Redirection not allowed to download assemblies.");
return;
}
using (Stream responseStream = wresp.GetResponseStream()) {
byte [] buffer = AssemblyPart.StreamToBuffer(responseStream);
if (IsZip(buffer))
{
// unzip it.
using (MemoryStream dest = new MemoryStream()) {
using (MemoryStream source = new MemoryStream(buffer)) {
ManagedStreamCallbacks source_cb;
ManagedStreamCallbacks dest_cb;
StreamWrapper source_wrapper;
StreamWrapper dest_wrapper;
source_wrapper = new StreamWrapper(source);
dest_wrapper = new StreamWrapper(dest);
source_cb = source_wrapper.GetCallbacks();
dest_cb = dest_wrapper.GetCallbacks();
// Zip files may contain multiple assemblies, all of which need to be loaded. Keep
// attempting to open subsequent files until it fails.
for (int i = 0; ; i++)
{
if (!NativeMethods.managed_unzip_stream_to_stream_nth_file(ref source_cb, ref dest_cb, i))
{
break;
}
if (Load(dest.ToArray(), kind) == null)
{
EmitError(2153, String.Format("Error while loading '{0}'.", wreq.RequestUri));
}
source.Position = 0;
dest.SetLength(0);
}
}
}
}
else
{
if (Load(buffer, kind) == null)
{
EmitError(2153, String.Format("Error while loading '{0}'.", wreq.RequestUri));
}
}
}
Dispatcher.BeginInvoke(AsyncDownloadComplete);
}
catch (Exception e) {
// we need to report everything since any error means CreateApplication won't be called
EmitError(error_code, e.ToString());
}
}