Data Loss Prevention policy making OpenMsgStore fail (0x80040312) - exchange-server

When DLP policy is enabled, Redemption fails with the error:
"All business e-mail messages are protected based on a policy set in your organization. There was an error opening the protected e-mail message."
ulLowLevelError: 2147746578 (i.e. 0x80040312)
ulContext: 805701633 (0x30060801)
Is there any way around this?
The error occurs when trying to access the IPMRootFolder property of a Store object:
// A previous version of the code was multi-threaded, it is no longer.
Session = OutlookRpcLoader.new_RDOSession();
Session.Logon(ProfileName: profile, ShowDialog: false, NewSession: true);
var stores = Session.Stores;
var store = stores["{STORE-NAME}"];
var root = store.IPMRootFolder;
The call stack shows that Redemption.IRDOStore.get_IPMRootFolder() threw the exception.
Edit
This is seen when using Redemption version 5.22.0.5498 loaded via the RedemptionLoader class in .NET (registry-free COM).
When testing with Redemption version 5.19.0.5238 from VBScript using CreateObject(), the error doesn't occur.
Could anything have changed between v5.19 and v5.22?

First of all, you need to detect where your code is running - whether it is the foreground or background thread. I'd suggest checking the ThreadID of the process. The foreground thread has the value set to 1. All background threads will values greater than one. If it is a secondary thread you need to create a new Redemption session on a secondary thread where you are going to use and set the MAPIOBJECT property to the object retrieved from the main thread. For example, a raw sketch in VB.NET:
Dim PrimaryRDOSession As New Redemption.RDOSession()
PrimaryRDOSession.Login([...])
Dim WorkerThread as New System.Threading.Thread(AddressOf ThreadProc)
WorkerThread.Start(PrimaryRDOSession.MAPIOBJECT)
Sub ThreadProc(ByVal param as Object)
Dim ThdRDOSession As New Redemption.RDOSession()
ThdRDOSession.MAPIOBJECT = param
' do other stuff
End Sub
Don't use objects created on the main thread if you are on a secondary one. Ensure you are consistent when using the objects.

I believe this was caused by AppLocker rules blocking unsigned binaries. The resolution was to either code-sign the files or add the program to the AppLocker allow-list.

Related

Session_OnEnd event on Global.asa, concurrency issue

In my application,I am using Session_OnEnd event on global.asa file to log the logged out user details to one of my table. For that I am creating an object of one of my VB component from Session_OnEnd event and from there I am inserting into one of my table.
In certain scenarios (Multiple user’s session end happens at a time), we are getting an Unhandled exception while creating above object, since my 1st request is already in processing status.
Anybody of you suggest any good method to overcome this issue?
Dim objClean
Set objClean= Server.CreateObject("Clean.clsClean")
Call objClean.Cleanup(Session, Application)
Set objClean= Nothing
Set objClean= Server.CreateObject("Clean.clsClean") this line is throwing an exception in my case.

How to retrieve the process's unique workflow number, while launching it through C# API?

I'm struggling for 4 days now.
There's this C# Process Engine API:
https://www.ibm.com/support/knowledgecenter/en/SSNW2F_5.2.1/com.ibm.p8.pe.dev.doc/web_services/ws_reference.htm
What I need to do is to retrieve the WorkflowNumber when launching the workflow, so later I can find that process in the system.
The issue here is that when you launch it - it returns the LaunchStep (the first step in the workflow) which doesn't have that ID assigned yet - it's null. The only thing available is the LaunchStep's WOBNumber.
In order to assign the Workflow ID to the step, you need to dispatch the step, so I do that:
UpdateStepRequest request = new UpdateStepRequest();
UpdateFlagEnum flag = UpdateFlagEnum.UPDATE_DISPATCH;
request.updateFlag = flag;
request.stepElement = element; // add the launch step
session.Client.updateStep(request);
And here the funny part happens. From this point, there is complately no option to retrieve that, because StepElements are stateless, updateStep() returns nothing and the best part - the LaunchStep is now destroyed in the system, because it's a LaunchStep - it just gets destroyed after the launch.
Any tips would be appreciated!

MVC3 Passing ControllerContext to thread?

I am using Rotativa in my MVC3 app to generate pdfs into a memory stream which is then emailed out as an email attachment. This works fine but it is quite slow (~5-7 seconds with just 1 user) so I've been trying to put it into a separate thread so the user doesn't get stuck with a huge delay.
The problem I've been facing is that Rotativa requires the Controller Context to generate the data into the memory stream, which means that if you try to put it in a separate thread and return a notification to the user then the context is disposed and the pdf generation will fail.
Unfortunately I do an email validation check on the server-side and return a true/false where appropriate, false will prompt the user to fix it and try again. This means I can't just assume that the email is always valid (I could do it by jquery, but if they turn it off and try to submit they won't get an error message).
So far I have tried:
Creating a new thread and passing the context in
Duplicating the context by copying it to a new variable
Serializing the context, passing the stream to the new thread and de-serializing (unfortunately the context is not serializable)
Has anyone got any other ideas?
Here is what I do to run a long process in the background with context. I'm using custom sessions backed by a database. You'll need to pass whatever values you need into the "background" action.
using (var client = new WebClient())
{
var values = new NameValueCollection
{
{ "sessionid", DataSession.Id.ExtractSid() }
};
client.UploadValuesAsync(new Uri(Url.AbsoluteAction("ResultsCallback", "Quote")), values);
}

IBM MQSeries ActiveX Write Message Error

I've a VB6 application with MQSeries Automation Classes for ActiveX. The problem is when i'm writing the message con the queue. I use this code :
This is how I open the connection and the relative queue :
Set MQSess = New MQSession
//Access Queue
Set QMgr = MQSess.AccessQueueManager(QueueManagerName)
Dim Queue As MQQueue
Dim msg As MQMessage
Dim pmo As MQPutMessageOptions
Dim ArrCar() As Byte
Set pmo = New MQPutMessageOptions
Set Queue = QMgr.AccessQueue(QueueName, OpenOption , RemoteQueueManagerName)
//OpenOption is a integer with value of 16 (MQOO_OUTPUT)
strMsgAppo = Translate("*MESSAGE_TO_INSERT*", ASCII_To_EBCDIC_Table())
ReDim ArrCar(Len(strMsgAppo) - 1)
For lngI = 1 To Len(strMsgAppo)
ArrCar(lngI - 1) = Asc(Mid(strMsgAppo, lngI, 1))
Next lngI
Call msg.Write(ArrCar) //Write the ByteArray
Call Queue.Put(msg, pmo)
The ASCII_To_EBCDIC_Table is a function used to change the encoding.
The error i'm getting from MQ is :
MQAX200.MQMessage::Write CompletionCode = 2, ReasonCode = 2043, ReasonName = MQRC_OBJECT_TYPE_ERROR
Is Anyone using this activex and can help me on how to write message in a queue?
In the code snippet provided, I'm not seeing where the connection to the QMgr is made nor where the queue is opened. Both of these steps must be completed before it is possible to put messages on the queue.
The 2043 reason code occurs when there is an invalid option in the Message Options field for a PUT or an OPEN. In this case the problem could either be on the PUT or an implicit OPEN, depending on what's in the code that was not provided and whether it contains an OPEN.
My suggestion would be to refer to the .Net samples provided in the installation and reconcile between those and your application. The samples reside at C:\Program Files (x86)\IBM\WebSphere MQ\tools\dotnet\samples in a default V7 installation.
The failure is on your msg.Write, and you should probably be using the .WrirteString method instead, after setting the .CharacterSet property to 37 (EBCDIC).
The hackish approach of your Translate() function might work, but only if assigned to a Byte array. As you have things you're likely to see scrambling when the data is converted back to Unicode. Or if Translate() does return a Byte array you'll have a mess with 8-bit data in a Unicode String (which can be fine but not with this MQ library).
You can probably just throw Translate() and your table away.
The IBM manual on this API is called "Using the Component Object Model Interface." Check it out!

In VS2010, is there a way to know which application pool a given w3wp.exe is serving, to then decide to attach the debugger to?

So I'm debugging some websites (one from trunk, one from branch) running locally, in separate apppools. I have trunk and branch solutions open in two VS instances. I'd like to debug trunk in one, and branch in the other. I'd like to know if there's a way to know which application pool each w3wp.exe is serving, to know which one is which when attaching the debugger.
Update: the point of this is to write a macro within VS to then let me have a button (per app-pool that is interesting) which will be clickable to attach the debugger to. So solutions should preferably not involve other programs.
Update2: this is on Windows 7 against IIS7.
Below is my core macro. Write a few one-line subs calling it, like AttachToW3wp("DefaultAppPool") naming each app pool you’re interested in, and make buttons and hotkeys for them.
Private Sub AttachToW3wp(ByVal appPoolName As String)
Const processName As String = "w3wp.exe"
Dim userName As String = String.Format("IIS APPPOOL\{0}", appPoolName)
Try
Dim debugger As EnvDTE90.Debugger3 = CType(DTE.Debugger, EnvDTE90.Debugger3)
'debugger.DetachAll()
Dim transport As EnvDTE80.Transport = debugger.Transports.Item("Default")
Dim qualifier As String = Environment.MachineName '= My.Computer.Name
Dim engines(3) As EnvDTE80.Engine
engines(0) = transport.Engines.Item("Managed")
engines(1) = transport.Engines.Item("Script")
engines(2) = transport.Engines.Item("T-SQL")
Dim successMessage As String = String.Empty
For Each process As EnvDTE80.Process2 In debugger.GetProcesses(transport, qualifier)
With process
Dim fi As New System.IO.FileInfo(.Name)
If fi.Name = processName AndAlso (String.Compare(.UserName, 0, userName, 0, Len(userName), True) = 0) Then
If .IsBeingDebugged Then Throw New Exception(String.Format("{0} {1} is already attached to a debugger.", processName, userName))
process.Attach2(engines)
successMessage = String.Format("Attached to {0} for {1} ({2})", processName, userName, .ProcessID)
Exit For
End If
End With
Next
If successMessage = String.Empty Then
Throw New Exception(String.Format("{0} {1} not found.", processName, userName))
Else
Trace.WriteLine(successMessage)
End If
Catch ex As System.Exception
MsgBox(ex.Message)
End Try
End Sub
Another option would be the WADA - W3WP Advanced Attacher available in the Visual Studio Gallery. I found it by searching in the Online Gallery of Extension Manager for "attach worker".
Look at the answers to this question. There are built in scripts you can run from a command window to do this.
If you can execute a request on each branch, you could use something like Process Explorer or Task Manager to see which ID is which possibly as one may be taking up CPU cycles that is currently processing a request assuming you can get such separation.
You can use task manager to view the user name under which the process is running (which in general is the same as the application pool name) and the process ID, but you have to turn on these columns in task manager, and also the process name has to be the same as the application pool (which is the default as far as I know).
Also note that all methods listed on this page might only display the processes that are currently running, which means that if your particular process has shut down due to idle time you have first to use the site in order to bring the process up in the list, and in your case it means you should first access all sites to make sure that the process associated with them is runing.

Resources