Locating the source DLL behind a COM+ ProgId - asp-classic

I've never really had to debug Classic ASP, so this is a little rough and most likely a poor question, but I have done as much research as I could before asking.
I have a request to identify what code prints to a printer, and re-use that code in a new page that someone has built.
While trying to identify that, I've stumbled on a few things that I don't understand, but namely one big one.
The gist is, people can order cookies from the cafeteria, and when they submit, it shows a confirmation page and that order is sent to a printer.
To get a list of cookie options, there's a Server Object created, and from there a method exists, but I cannot identify where it is or where I should be looking. Here's the code:
<%
On error resume next
Const CATAGORY_COOKIE = 1
Dim cookieNames
Dim objCookie
Dim Count
Set objCookie = Server.CreateObject("CookieOrder.CookieRequest")
if objCookie Is Nothing then
Response.Write "Error"
Response.End
End if
cookieNames = objCookie.getAvailable_Item_Names(CATAGORY_COOKIE)
Count = objCookie.Count
Dim sz
sz = Split(cookieNames, ";")
Set objCookie = Nothing
%>
How do I identify what the Server Object is? There's a .dll file that contains binary, but I'm not familiar with how that could be utilized.
I have tried to follow the browser dev tools, but they really haven't been too helpful in this aspect.
I am hoping that learning how this code is executing or where it's being executed I will figure out my other problems.

Bit of background
The project is using a COM+ component. These are defined in Classic ASP using the syntax;
Set obj = Server.CreateObject("[insert COM+ ProgId]")
In this project you are using a component registered with the ProgId
CookieOrder.CookieRequest
There are many out of the box COM+ components available to Classic ASP that provide a lot of common functionality such as;
Visual Basic Scripting Runtime
ActiveX Data Objects
There is also the ability to create COM+ components for use with Classic ASP using languages common to the time like Visual Basic, Visual C++ and more recently using the .NET Framework (C#, VB.NET).
How to locate COM+ libraries
NOTE: Please be careful when accessing the registry as modifying or deleting keys could lead to a corrupt operating system.
Also for the purposes of this guide will use the Scripting.Dictionary ProgId.
The key is using the ProgId to find an elusive COM+ library.
Start %SystemRoot%\system32\regedit.exe (will work in most Windows Operating Systems)
Navigate to the HKEY_CLASS_ROOT hive and select it, then press Ctrl + F to open the Find dialog box.
In Find what type the ProgId in this case Scripting.Dictionary and make sure in look at only Key is checked then press Find or Find Next.
If a ProgId key is found expand to the key and locate the CLSID key which contains a (Default) REG_SZ with the value of the CLSID in the case of this example {EE09B103-97E0-11CF-978F-00A02463E06F}. Double click this value to bring up the Edit String dialog copy the value into your clipboard.
Return to the HKEY_CLASS_ROOT key and use Find to search for the CLSID value which in this example is {EE09B103-97E0-11CF-978F-00A02463E06F} and again make sure Look at has only Key checked then press Find or Find Next.
If the key is found expand and locate the InprocServer32 key in it you will find the location of DLL in the (Default) REG_SZ value. In this example that is C:\Windows\System32\scrrun.dll (this will be different depending on installation location and OS)
What about decompiling?
There's a lot of assumption in the comments about the compiler used to compile the DLL (mainly .NET), but the best way to check is to use one of the many programs out there in the public domain designed for this purpose.
There is a specific question on SO that deals with this;
Answer by #simon-mᶜkenzie to Identifying the origin of a DLL

Related

COM visible .NET class cannot get System.Web.HttpContext.Current when used in classic asp

My company would like to update legacy visual basic 6/classic asp code. We do not have access to a visual basic 6 compiler, so it seemed like a good idea to use Visual Studio 10 and recompile the visual basic 6 code as a VB.NET class. With some minor modifications everything compiled and we registered it as a com object to be called from classic asp.
Now we are trying to access global variables from the asp server. After an extensive search on Google, the only way mentioned was to use System.Web.HttpContext.Current or System.Web.HttpContext.Current.Application . However, this doesn't appear to work.
Here is the code leading up to error. We have imported System and System.Web.
Public Function DoSomethingUseful() As String
Dim objCurrent As System.Web.HttpContext
DoSomethingUseful = Nothing
objCurrent = System.Web.HttpContext.Current
If objCurrent Is Nothing Then
Throw New Exception("No Context.") '<--- THIS EXCEPTION IS THROWN
End If
The problem is we can't get a current instance of the http context and the exception is thrown. Every example I've seem shows that the line objCurrent = System.Web.HttpContext.Current should work but it doesn't. Perhaps it's because we are not using ASP.NET? If not then why isn't it working?
Yes, it is because you're not using ASP.NET.
Despite the similar sounding names, and to a certain degree similar design choices, there is no relationship whatsoever between ASP.NET anything and "Classic" ASP anything. They are completely independent environments.
To access directly the ASP context objects (not the similarly-named ASP.NET context objects which in your application don't even exist), your object must be a registered COM+ object, so:
Your class must inherit from System.EnterpriseServices.ServicedComponent *
On Windows 7/2008 and up, you must enable the "Allow IIS Intrinsic properties" from Component Services, just like you would have to in VB6 (open \Component Services\My Computer\COM+ Applications\YourComPlusApp\Components; select all the objects that need the ASP objects; right-click; click on Properties; go to the Advanced tab).
You can then retrieve the ASP objects (Application, Server, Request, Response, Session) from the COM+ ObjectContext.
Your code would look something like this:
objCurrent = System.EnterpriseServices.ContextUtil.GetNamedProperty("Application")
There are also attributes that you can add to your class to simplify the deployment of the code, but that's a bit outside the scope of this question.
For your reference:
ASP Built-in Objects
ContextUtil.GetNamedProperty Method
* I don't remember 100% if this is a hard requirement. It might actually depend on what the object is actually doing with COM+.

Server.CreateObject Failed with chiliupload component

I get the following error with a legacy asp application that I have been asked to help out with.
Server object error 'ASP 0177 : 800401f3'
Server.CreateObject Failed
/site_manager/image_upload.asp, line 27
800401f3
The line ofcode that throws the error is shown below:
Set fbase = Server.CreateObject("chili.upload.1")
As you ahve probably guessed oldschool asp isn't my strong point but from the research I have done it seems as if a component hasn't been registered on the server (I only have FTP access).
What component needs to be regsistered?
Thanks for the help...
You're missing the registration of the DLL that creates the chili.upload.1 object. Are you trying to run this on a Linux machine?
You need to register the Sun Chili!Soft ASP components. Here's the manual on this from 2003:
http://ns7.webmasters.com/caspdoc/html/running_the_setup_program_sun_chili_soft_asp_for_windows.htm. Note that this only works if you still have the original setup. Otherwise you're out of luck. Sun Chili!Soft ASP is no longer available and very, very dead.
If you're just interested in file upload functionality on ASP, I can recommend Free ASP Upload. It requires no registration of any components and generally works. I can also recommend this article on the topic of ASP uploads. If you're willing to shell out some money there are hundreds of components that do the same thing too.
Register the DLL on your computer, and then do this:
Locate and then click the following registry subkey:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\MAIN\
FeatureControl\FEATURE_IGNORE_ZONES_INITIALIZATION_FAILURE_KB945701
Note If the FEATURE_IGNORE_ZONES_INITIALIZATION_FAILURE_KB945701 subkey does not exist, you must manually create it. If you're using a 64 bit OS, you may need to use HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Internet Explorer\MAIN\ FeatureControl\FEATURE_IGNORE_ZONES_INITIALIZATION_FAILURE_KB945701 instead
Right-click FEATURE_IGNORE_ZONES_INITIALIZATION_FAILURE_KB945701,
point to New, and then click DWORD Value
Type w3wp.exe to name the new registry entry, and then press ENTER.
Right-click w3wp.exe, and then click Modify.
In the Value data box, type 1, and then click OK.
After setting this registry key, a simple app pool restart will apply the change. No longer will your .NET COM components randomly stop working with no real solution except shuffling application pools!

ASP.NET unit testing Windows7/IIS7

Spent several hours today trying to write some unit tests against an ASP.NET project. It's Visual Studio 2010.
Using Windows 7 Enterprise with IIS7.
Steps I took were:
Added a new test project to the solution
Opened a class file as part of the web site (Member.vb)
Right clicked within the class file and "Generate unit tests"
Select the methods I wish to generate stubs for, choose to add to my test project, click OK
Open up the generated MemberTest.vb file in the test project, click within one of the generated tests, click "Run tests in curent context"
When following these precise steps on my Windows XP Professional with IIS6 machine it works fine.
However on the Windows 7 Enterprise machine on IIS7 I get:
The URL specified ('http://localhost/MyProject') does not
correspond to a valid directory. Tests configured to run in ASP.NET in
IIS require a valid directory to exist for the URL. The URL may be
invalid or may not point to a valid Web application.
So what's going on, I can confirm I can browse to http://localhost/MyProject and it displays perfectly.
I feel sure I'm missing some sort of config in Windows/IIS but I'm really at a loss.
Generated test method:
<TestMethod(), _
HostType("ASP.NET"), _
UrlToTest("http://localhost/MyProject")> _
Public Sub MyMethodTest()
Dim target As Member_Accessor = New Member_Accessor() ' TODO: Initialize to an appropriate value
Dim CurrentVal As Short = 0 ' TODO: Initialize to an appropriate value
Dim expected As Short = 0 ' TODO: Initialize to an appropriate value
Dim actual As Short
actual = target.MyMethod(CurrentVal)
Assert.AreEqual(expected, actual)
Assert.Inconclusive("Verify the correctness of this test method.")
End Sub
(Cross-posted at ASP.NET Forums)
This could be a permissions issue.
If you're using the default directory (C:\users\\Documents\Visual Studio 2010\Projects), the app identity pool does not have permissions there. You'd have to create a project in something like C:\webs and make sure app pool identity has permission to the folder.
Refer to Rick Anderson's blog post at http://blogs.msdn.com/b/rickandy/archive/2011/04/22/test-you-asp-net-mvc-or-webforms-application-on-iis-7-in-30-seconds.aspx and see if that helps.
If you have not done unit testing before, I would really recommend that you start by just testing the functionality of your classes as cleanly as possible. Try to break you you functionality into small pieces that can be tested individually without and dependencies to the web context.
Have a look at this question for an idea about What is unit testing
Here is an MSDN Magazine article about testing
You can also have a look at this Blog. The examples are using NUnit but the principal is the same if you are using MSTest.
I can also recommend Roy Osheroves Book Art of unit testing
In you case if the Member class does not have dependencies to web context you don't need the IIS and could instead just do something like this:
<TestMethod()> _
Public Sub MyMethodTest()
Dim target = New Member()
Dim CurrentVal As Short = 0 ' TODO: Initialize to an appropriate value
Dim expected As Short = 0 ' TODO: Initialize to an appropriate value
Dim actual As Short
actual = member.MyMethod(CurrentVal)
Assert.AreEqual(expected, actual)
End Sub
I ran into the same problem today. After some research, I found this thread which suggested I check my event log. Upon doing that, I discovered numerous errors similar to the following:
(QTAgent32.exe, PID 12348, Thread 61) WebSites.GetWebServer: failed to
create AspNetHelper:
Microsoft.VisualStudio.Enterprise.Common.AspNetHelperException: The
website metabase contains unexpected information or you do not have
permission to access the metabase. You must be a member of the
Administrators group on the local computer to access the IIS metabase.
Therefore, you cannot create or open a local IIS Web site. If you
have Read, Write, and Modify Permissions for the folder where the
files are located, you can create a file system web site that points
to the folder in order to proceed. --->
System.Runtime.InteropServices.COMException: Unknown error
(0x80005000)
That lead me to this blog post which seems to have resolved the issue.
I just needed to go to "Turn Windows features on or off" and add IIS 6 Management Compatibility and all four subcomponents. I'm running Windows 7 Home Premium which doesn't have the Windows Authentication option, but that didn't seem to be an issue. Give it a shot and see if that resolves the issue for you.
You may need to enable "Use IIS" in the project properties, then click "Create Virtual Directory". Do you have IIS Express installed?

How to run a VBScript in a Qt application without involving cscript.exe or wscript.exe?

I am writing a Qt application that calls QProcess::startDetached("wscript.exe script.vbs") to show the delete confirmation dialog in Windows.
this is the script:
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.Namespace("-")
Set objFolderItem = objFolder.ParseName("-")
objFolderItem.InvokeVerb("Delete")
the arguments for Namespace and ParseName are from the arguments passed to the script.
This may be inefficient because it opens an external application first before running the script. I was wondering if i can run VBScripts in a Qt application.
If not, what alternatives can i do?
My VBScript is very weak, so I'm not 100% sure I understand what you are trying to do. My assumption is that you are trying to delete a folder, but want to give the user the normal confirmation box and animation while the action is occurring. If that is not correct, please let me know and I will remove this answer.
A few ideas:
You could call the Windows API directory within your C++ code to do this. I believe the correct call would be to use IFileOperation (Vista and later) or SHFileOperation (pre-Vista)
Qt already has message box dialogs. Although you might not get the exact same functionality as the native shell, you could use this (QMessageBox::warning) and then delete the folder using QDir. This would also be cross-platform portable.
If you stick with the VBScript, I doubt you would see any performance issues unless this is being called many, many times in a loop or something. You know, the old "premature optimization is the root of all evil" thing.
You should read up on the IActiveScript COM interface. You can create an instance of an interpreter that implements IActiveScript to provide a runtime for evaluating scripts. VBScript and JScript can both be used for this and a number of other third-party scripting languages also provide IActiveScript support.
The overview for working with this is you create a language runtime (an instance of VBScript for instance) then add some custom objects to it. Typically if you are embedding an interpreter into your application then exposing an Application object is a good place to start. This can be just an IDispatch interface or something more concrete with an IDL generated typelibrary and all the trimmings. Once you have added the necessary named items into the runtime you load one or more scripts. Any public functions or subroutines declared in the scripts now get exposed via the IDispatch interface of the live runtime once you switch its state to active or running. To actually run the script program, I invoke the Main function for my stuff - you could choose some other scheme as applicable to your environment.
The nice thing about ActiveScripting, is to change language you just change the runtime CLSID. So if people prefer Perl they can use PerlScript or PythonScript etc. Your Application object remains the same hence you don't have to write additional code to support the new languages. The only requirement is that everything is COM.

GetObjectContext returns nothing in VB6 COM dll, called from classic ASP

I am debugging this Active X dll using the VB6 IDE. I can see the execution get as far as an attempt to GetObjectContext. This method always returns NOTHING.
This is happening on Windows 7 32 bit, IIS 7. (The application is working in other locations, one of which is Windows Server 2008 with IIS 7)
I have Googled extensively and found many references to this relating to COM+, but there is NO COM+ involved in my scenario. Just plain old Server.CreateObject from a registered dll.
I have ASP code as follows
SET objCalendar = Server.CreateObject("SSYSDEV.Calendar")
objCalendar.BuildCalendar("ADMINUSERS")
SET objCalendar = Nothing
The problem lines of the requested function in the dll are:
Dim objHttpRequest As ASPTypeLibrary.Request
Set objHttpRequest = GetObjectContext.Item("Request")
Any help or suggestions, as always, will be greatly appreciated.
I'm still getting over the shock of having to work with VB6 - I never thought it would happen! It's like being dragged back to the dark ages, in a very rough fashion that's causing blisters!
P.S. I have also set up a COM+ component and had the ASP get the object that way, GetObjectContext returns an empty object in this case, which has no ASP objects in it. So this is no help :-(
I know this is a little late, but I had a similar problem and this solved it for me:
Thread: Problem accessing Request object via COM+
http://forums.iis.net/t/1146404.aspx
Summary: turn on 'Allow IIS Intrinsic Properties' in the COM+ component.
I've found that the COM+ approach to using VB6 components in IIS to be a bit flaky. I add this to a VB6 class that I want to instance in ASP::-
Private moScriptCtx As ScriptingContext
Public Sub OnStartPage(SC As ScriptingContext)
Set moScriptCtx = SC
End Sub
You can now access Request,Response,Server etc as properties of the moScriptCtx object.
You might be wondering how you call OnStartPage in the first place. You don't ASP automagically does that for you during the CreateObject execution.

Resources