Solved

Reading PARAM from HTML OBJECT  into EXE inside CAB

Posted on 2002-05-23
17
1,142 Views
Last Modified: 2013-11-18
OK a simple question.

I have a signed CAB called "test.cab"
containing an executable called "test.exe"
and an INF file called "test.inf"

This is not an ACTIVEX program just a normal win32 APP that is run through a signed CAB.  All that is required in the INF file is the following.

[Setup Hooks]
   hook1=hook1
[hook1]
   run=%EXTRACT_DIR%\test.exe
[Version]
   signature="$CHICAGO$"
   AdvancedINF=2.0

To run "test.exe" from the webpage (after accepting the signed certificate) the following OBJECT tag is used.

<OBJECT CLASSID="CLSID:15589FA1-C456-11CE-BF01-A0055595A" CODEBASE=test.cab>
</OBJECT>

------
OK ... all is fine.  BUT now I want to use a PARAM tag in the object which I can pickup in my executable.  This is so easy to do with a JAVA applet but I have no idea within a win32 app.

ie. put
<PARAM NAME="id" VALUE="666">
within the OBJECT html and read in the variable id at runtime within the EXE.

Thats all.

Thanks in advance

0
Comment
Question by:chulland
  • 7
  • 7
  • 2
  • +1
17 Comments
 
LVL 2

Expert Comment

by:mirtol
ID: 7030646
Check out the environment variables :o)
0
 

Author Comment

by:chulland
ID: 7030661
Please elaborate with an example.
0
 

Author Comment

by:chulland
ID: 7030684
I don't want to use cookies either,
Just want a solution as simple as it is in JAVA
ie.

userid = Integer.parseInt(getParameter("id"));

There must be a way as simple in c++ as there is in Java.
0
 
LVL 2

Expert Comment

by:mirtol
ID: 7030732
I'm sorry I was so ambiguous...

>> What compiler are you developing in?

The PARAM statements just set ActiveX properties - create the properties. This will make it VERY easy to implement.

Otherwise you have to check your environment using interface calls.

It's easiest if you read up on your own compiler's help file about ActiveX properties... but if you're using an IDE you should be able to do it very quickly indeed and then you can just reference the property to find the value.
0
 

Author Comment

by:chulland
ID: 7030803
What has this to do with the compiler? Like I said before its not really an activex component (com object) just a simple win32 inside a CAB.  An installer, thats all.

All I need to do is call the "installer" with different options WITHOUT the need to "re-cab".

Its just the same as calling any executable with command line options .... in this case the options are required to be taken from the OBJECT tag.

ANY code examples of how to retrieve the PARAM tag in VC++ will be helpfull.
0
 
LVL 22

Expert Comment

by:ambience
ID: 7031180
>> <OBJECT CLASSID="CLSID:15589FA1-C456-11CE-BF01-A0055595A" CODEBASE=test.cab>
</OBJECT>

Do you know which object's CLSID this is ?

Its either an installer or extractor that uses codebase to download and extract and run the cab files
Or
You app must definitely have this object otherwise the object creation in HTML would fail and report an error.

In either case check if that object supports passing params to the extractable or the executable after it is extracted. If its an installer it most definitely has support for command line params etc. In either case post some information about that object.

How do you specify that test.exe be run after extraction, can you not specify additional command line params there ?

You can most definitely retrieve PARAM tags in VC++, but would it really help or even aply at all here. How would you access the HTML document ??? This is going to be a hard ride if at all
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7031328
Standard Exe programs do not implement a method to access the PARAM= value.  I can suggest several options:

* EXEs can read data from the command line, so you could change the run= line in your INF file.

* Add an INI file to the CAB and have the EXE read from it.

* Rewrite your EXE so that it is an ActiveX object that implements IPersistPropertyBag

* Write a small ActiveX wrapper that reads the PARAMs and passes them to the EXE on its command line or via another mechanism

* Try some tests... maybe the installation component passes the PARAM values on the command line (I have seen nothing that even suggests this, but what the heck, its worth a try).

-- Dan
0
 

Author Comment

by:chulland
ID: 7031408
Thanks for you replys, let me try and answer your answers in more detail.

* Do you know which object's CLSID this is ?
-------------------------------------------------------
This is taken straight from Microsoft support using a method call "Internet Code Download Linking"
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q232077
It's a method to run executables from webpages.  It does run very much like an installer.

* How do you specify that test.exe be run after extraction, can you not specify additional command line
params there ?
-------------------------------------------------------
If you look at what is in my INF file you can see run=%EXTRACT_DIR%\test.exe

Now to answer both people on this fact that I can add command line options to this.... yes I could but this INF is contained within the signed CAB.  I need to call the program from OUTSIDE with various command line options depending on my HTML form options, so this is not possible.

* Rewrite your EXE so that it is an ActiveX object that implements IPersistPropertyBag
-------------------------------------------------------
This is a very drastic way of curing a problem although it would work I admit :)

* Write a small ActiveX wrapper that reads the PARAMs and passes them to the EXE on its command line
or via another mechanism
-------------------------------------------------------
Yes this would be another way.  Basically use a small activex program to download the larger program to disk then run with command line options.... but thats why I asked the question.  Its very easy to do this in a signed java Applet in about 40 lines of code.  I wanted to see if anyone knew a straight forward way of doing it.

----------
Ok I'll continue to do tests myself, if anyone has any other ideas then please post.

Thanks

0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 49

Expert Comment

by:DanRollins
ID: 7031537
>> Basically use a small activex program to download the larger program...

Not what I meant.  The cab could contain both files (treat the EXE as a dependency, e.g., like a DLL required by the ActiveX).  When the ActiveX gets control, it reads the PARAM settings and formulates a rich commandline and then launches the EXE.

I'm not saying this is the best way, but it might work.

I did some testing, and found that the PARAM= values do not end up as commandline arguments or in the process environment strings.

-- Dan
0
 

Author Comment

by:chulland
ID: 7031720
Hi Dan

Done tests also and can't get anything from command line either.  Also tried just using a signed EXE rather than a CAB but the CODEBASE tag won't allow options after the .exe

The Small ActiveX interface like you suggested looks the best way at the moment but I wanted to avoid it.  I wouldn't really know where to start with it either.  An example of how this would be done would be very usefull.

Its strange that such a "simple" task cannot be performed, but I guess that IE for you.

Thanks
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7032611
>>but I guess that IE for you.
Does it work with Netscape or Opera?  Just curious.  If you shoot your horse, you have to walk...

-- Dan
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7034150
>>An example of how this would be done would
be very usefull.

1) New project, ATL COM AppWizard
   Name: Starter
   [OK]
2) Dynamic Link Libraty (DLL)
   [x] Allow merging of proxy/stub
   [Finish]
3) ClassView, select Starter
   Right-click: New ALT Object
   Simple Object
   ParmReader
   [OK]
4) Edit ParmReader.h to...

// ParmReader.h : Declaration of the CParmReader

#ifndef __PARMREADER_H_
#define __PARMREADER_H_

#include "resource.h"       // main symbols
#include <atlctl.h>

/////////////////////////////////////////////////////////////////////////////
// CParmReader
class ATL_NO_VTABLE CParmReader :
     public CComObjectRootEx<CComSingleThreadModel>,
     public IDispatchImpl<IParmReader, &IID_IParmReader, &LIBID_STARTERLib>,
     public CComControl<CParmReader>,
     public CComCoClass<CParmReader, &CLSID_ParmReader>,
     public IPersistPropertyBagImpl<CParmReader>
{
public:
     CParmReader()
     {
     }
     // --- added
     STDMETHODIMP Load(IPropertyBag* pPropBag,IErrorLog* pErrorLog);

DECLARE_REGISTRY_RESOURCEID(IDR_PARMREADER)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CParmReader)
     COM_INTERFACE_ENTRY(IParmReader)
     COM_INTERFACE_ENTRY(IDispatch)
     COM_INTERFACE_ENTRY(IPersistPropertyBag) // <<-- added
END_COM_MAP()

BEGIN_PROP_MAP(CParmReader)
     PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
     PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
     // Example entries
     // PROP_ENTRY("Property Description", dispid, clsid)
     // PROP_PAGE(CLSID_StockColorPage)
END_PROP_MAP()

// IParmReader
public:
};

#endif //__PARMREADER_H_

=-=-=-=-=-=--==-=-=-=-
continued...
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 300 total points
ID: 7034159
5) Edit ParmReader.cpp.  Make it so:

// ParmReader.cpp : Implementation of CParmReader
#include "stdafx.h"
#include "Starter.h"
#include "ParmReader.h"

/////////////////////////////////////////////////////////////////////////////
// CParmReader

STDMETHODIMP CParmReader::Load(IPropertyBag* pPropBag,IErrorLog* pErrorLog)
{
    if (0 == pPropBag) {
        return(E_POINTER);
    }
    VARIANT varMyNum;
    VARIANT varMyName;
    ::VariantInit(&varMyNum);
    ::VariantInit(&varMyName);
    pPropBag->Read(L"mynum",&varMyNum,0);
    pPropBag->Read(L"myname",&varMyName,0);


    /* convert, store or work with results here */

    ::VariantClear(&varMyNum);
    ::VariantClear(&varMyName);
     return( S_OK );
}
=-=-=-=-=-=-=-
6) Build: It should compile and link without errors

7) Create this file, named C:\Temp\ParmTest.htm
=-=-=-=-=-=-=-
<html>
<body>
 Hi there!<br>
 <OBJECT name="WhoCares"
  classid="clsid:......"
  style="width=30;height=30">
 <PARAM NAME="mynum"  value="12">
 <PARAM NAME="myname" value="Dan">
</OBJECT>

</body></html>

=-=-=-=-=-=-=-
Open up Starter.idl.  Copy the lowest GUID.  It is just above
   helpstring("ParmReader Class")

Paste that GUID into the HTM file, replacing the ......

Save the HTML file

I am now going to sabve you a LOT of time and effort:  

8) Place a breakpoint in CParmReader::Load()

9) Attempt to run/debug the Starter.DLL
It will prompt "what executable?".  Click > and choose Default Browser.

10) Click OK.  An empty IE will appear.  

11) Drag the HTML file and drop it into the browser (or type its full path into the address field).

That causes the ActiveX control to be instantiated.  The browser sees that there are parms so it queries the control for IPersistPropertyBag, finds it and calls its Load() member.

12) Execution stop at the breakpoint you set in step 8.  Single-step and note that the parms are indeed available for your hacking pleasure.

=-=-=-=-=-=-=-=-=-=-
I have never done this before.  It took several hours to work it all out.

-- Dan
0
 

Author Comment

by:chulland
ID: 7035086
Hi Dan,

You've been busy!  The code compiled and worked as you stated.  As far as an activeX solution goes you have given more than an adequate answer.  

I'm still disappointed that a more straight forward way of passing the PARAM through to an executable isn't available.  The size of the DLL created was itself over 20k with a release version which is half the size of the original install program, just to pass a variable to it.

I have played around with a few different options.  One was to write a cookie and my EXE read it back, another was to make a small Java Applet.  Both work fine but Cookies and Applets can both be "switched off" as indeed can ActiveX.  There is also the problem with different browsers as you mentioned, IE, Netscape, Opera and even AOL's.

I came up with a VERY simple solution to all this.

The browser window, that is thrown up allowing the download wether by signed code or simple "run from location" can have a title.  For instance "Download File".  If this title is changed to have extra info such as the information I wanted to pass in the PARAM ie. "Download-ID123" then we can use this.

In the downloaded EXE, I've added a routine that scans all IE windows and checks their titles for an ID.  The program can then execute according to that information.

STUPIDLY EASY!

This can easily be extended to include Netscape, Opera and AOL.  Here's the code, its very small.

static BOOL CALLBACK getid(HWND hwnd, LPARAM lParam)
{
  char title[32];
  char classname[32];

  GetWindowText(hwnd, title, 32);
  GetClassName(hwnd, classname, 32);

  if (strcmp(classname, "IEFrame") == 0 || strcmp(classname, "CabinetWClass") == 0}
  {
      // Strip ID off here and check if valid.
      // If OK set a variable.  Thats it!
  }
     return TRUE;
}

void CJPDApp::checkID()
{  
     EnumWindows((WNDENUMPROC)getid, (LPARAM)NULL);
}

------------------------------------------------------
Please give your comments.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7037866
>>There must be a way as simple in c++ as there is in Java.

>>Its strange that such a "simple" task cannot be performed, but I guess that IE for you.

>> I'm still disappointed that a more straight forward way
>> of passing the PARAM through to an executable isn't available.

Win32 C++ apps are inherently dangerous since they have full access to the computer.  For instance, it is possible to format the hard disk, or spam out thousands of emails or install a keyboard hook to monitor keyboard usage for passwords... etc.  So it shouldn't be too hard to understand why Microsoft does not make it easy to allow a click in a browser to cause download and execute an arbitrary program.  In fact, whenever somebody discovers a way to do that, Microsoft immediately comes out with a "Critical Update" to fix a "serious security breach."

Your technique of reading a parameter off of the download window title sounds like it will work for your application.

-- Dan
0
 

Author Comment

by:chulland
ID: 7038628
Hi Dan,

Any App, ActiveX, Java Applet etc can do such harm if used with a signed certificate.  Thats what its there for, the mechanism should be available to pass those variables if the app is signed.  It appears Microsoft overlooked this particular instance.

Anyway the solution for my particular app is working well as long as the download window remains open as the app starts to run.

I think your ActiveX answer was a good one for most people so it would be sensible to close this question and at least award you some of the points.

Thanks for your help on this.


0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7038668
I'm glad I could help.  -- Dan
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now