The MASM Forum Archive 2004 to 2012

General Forums => The Workshop => Topic started by: donkey on January 30, 2009, 02:16:37 AM

Title: Using HTMLHelp2 with DExplore
Post by: donkey on January 30, 2009, 02:16:37 AM
The PSDK and MSDN library are both examples of HTMLHelp2, though Microsoft has not really pushed the standard it is used in Visual Studio to display help files and I am writing an extension to the RadHelp plugin for RadASM that will allow it to use DExplore directly. The following is an example of a simple use of he COM interface for VSHelp80, the interface has very little documentation at MSDN, as a matter of fact for all of the information in the header file I was required to use OleView from the Microsoft toolkit and build the header that way. Both the IVSHelp and IVSHelp80 interfaces appear to work fine. The only problem I have is preventing the DExplore window from closing, I tried getting its pid/tid and using the wait functions but that was unsuccessful since the process and thread don't appear to close until the interface is released. I didn't feel like writing a message hook to watch for WM_CLOSE so I wrote a kludge for the example that checks to see if the window is visible, if not it releases the interface and shuts down.

VSHelp80.h (this will be included in the next header project release)
#IFNDEF VSHELP80_H
#define GUID_IID_IVSHelp <0x4A791148,0x19E4,0x11D3,0xB8,0x6B,0x00,0xC0,0x4F,0x79,0xF8,0x02>
#define GUID_IID_IVSHelp80 <0x78413D2D,0x0492,0x4A9B,0xAB,0x25,0x73,0x06,0x33,0x67,0x99,0x77>

#IFNDEF Unknown
Unknown STRUCT
   QueryInterface DD
   AddRef DD
   Release DD
ENDS
#ENDIF

#IFNDEF Dispatch
Dispatch STRUCT
GetTypeInfoCount DD
GetTypeInfo DD
GetIDsOfNames DD
Invoke DD
ENDS
#ENDIF

HELP STRUCT
Contents DD
Index DD
Search DD
IndexResults DD
SearchResults DD
DisplayTopicFromId DD
DisplayTopicFromURL DD
DisplayTopicFromURLEx DD
DisplayTopicFromKeyword DD
DisplayTopicFromF1Keyword DD
DisplayTopicFrom_OLD_Help DD
SyncContents DD
CanSyncContents DD
GetNextTopic DD
GetPrevTopic DD
FilterUI DD
CanShowFilterUI DD
Close DD
SyncIndex DD
SetCollection DD
GetCollection DD
GetFilter DD
SetFilter DD
FilterQuery DD
GetHelpOwner DD
SetHelpOwner DD
HxSession DD
Help DD
GetObject DD
ENDS

HELP2 STRUCT
SearchEx DD
HowDoI DD
Favorites DD
AskAQuestion DD
DisplayTopicFromURLEx2 DD
InitializeSettingsToken DD
ENDS

IVSHelp STRUCT
IUnknown Unknown <>
IDispatch Dispatch <>
Contents DD
Index DD
Search DD
IndexResults DD
SearchResults DD
DisplayTopicFromId DD
DisplayTopicFromURL DD
DisplayTopicFromURLEx DD
DisplayTopicFromKeyword DD
DisplayTopicFromF1Keyword DD
DisplayTopicFrom_OLD_Help DD
SyncContents DD
CanSyncContents DD
GetNextTopic DD
GetPrevTopic DD
FilterUI DD
CanShowFilterUI DD
Close DD
SyncIndex DD
SetCollection DD
GetCollection DD
GetFilter DD
SetFilter DD
FilterQuery DD
GetHelpOwner DD
SetHelpOwner DD
HxSession DD
Help DD
GetObject DD
ENDS

IVSHelp80 STRUCT
IUnknown Unknown <>
IDispatch Dispatch <>
Help HELP <>
Help2 HELP2 <>
ENDS

#define vsAskQuestionFlagsAskNew 0x00000001
#define vsAskQuestionFlagsCheckStatus 0x00000002
#define vsAskQuestionFlagsSendFeedback 0x00000004

#define vsSearchFlagsNone 0x00000000
#define vsSearchFlagsExecuteSearch 0x00000001
#define vsSearchFlagsAddToExistingQueryString 0x00000002
#define vsSearchFlagsFilterTransformSpecified 0x00000004

#define vsHelpDisplayUrlFlagsNone 0
#define vsHelpDisplayUrlFlagsHighlightTerm 1
#define vsHelpDisplayUrlFlagsOpenNewWindow 2
#define vsHelpDisplayUrlFlagsGuidLocal 16
#define vsHelpDisplayUrlFlagsGuidOnline 32
#define vsHelpDisplayUrlFlagsGuidLocale 64
#define vsHelpDisplayUrlFlagsGuidFailover 128
#define vsHelpDisplayUrlFlagsNamedUrl 256
#define vsHelpDisplayUrlFlagsNoHistory 512
#define vsHelpDisplayUrlFlagsNoHistoryThisPage 1024

#define HUFTID_Default 0
#define HUFTID_Local 1
#define HUFTID_Online 2
#define HUFTID_Locale 4

#define vsHelpSearchFilterTransformsHelp L"Help"
#define vsHelpSearchFilterTransformsControls L"Controls"
#define vsHelpSearchFilterTransformsSamples L"Samples"
#define vsHelpSearchFilterTransformsSnippets L"Snippets"
#define vsHelpSearchFilterTransformsStarterKits L"StarterKits"
#define vsHelpSearchFilterTransformsAddins L"Addins"
#define vsHelpSearchFilterTransformsUnfiltered L"Unfiltered"

#define DExploreWndClass "wndclass_desked_gsk",0

#ENDIF


The example for use with the latest MSDN library
#DEFINE IDISPATCH_DEFINED
#DEFINE IUNKNOWN_DEFINED

#DEFINE LINKFILES

#DEFINE NOMCX
#DEFINE NOIME
#DEFINE NOTV
#DEFINE NONETWORK
#DEFINE NOSERVICE
#DEFINE NOCON
#DEFINE NOCARD
#DEFINE NORADASM
#DEFINE NOZLIB
#DEFINE NODONKEY

#include "Windows.h"
#include "VSHelp80.h"
#include "macros.a" // For the CoInvoke macro

DATA SECTION
hInstance DD ?
IID_IVSHelp80 GUID GUID_IID_IVSHelp80
Collection DB "ms-help://MS.MSDNQTR.v90.en",0
Keyword DB "CoInitialize",0
wszNULL DB L"",0
pDExplore DD ?
hDExplore DD ?
hHook DD ?

CODE SECTION

Start:
Invoke CoInitialize,NULL
invoke GetInterface,"DExplore.AppObj"
test eax,eax
jz >>
mov [pDExplore],eax

invoke SetCollection,[pDExplore],offset Collection

invoke ShowTopic,[pDExplore],offset Keyword

invoke WaitForClose

invoke ReleaseInterface

:
invoke CoUninitialize
invoke ExitProcess,0

WaitForClose FRAME
LOCAL hwnd:D
LOCAL pid:D
LOCAL tid:D
LOCAL hThread:D

invoke FindWindow, DExploreWndClass, NULL
mov [hwnd],eax

:
invoke Sleep,125
invoke IsWindowVisible,[hwnd]
test eax,eax
jnz <

RET
ENDF

GetInterface FRAME ProgId
LOCAL wszProgID[1024]:W
LOCAL pInterface:D
LOCAL clsid :GUID

invoke MultiByteToWideChar,CP_ACP,NULL,[ProgId],-1,offset wszProgID,1024
// Get our Class ID
invoke CLSIDFromProgID,offset wszProgID, offset clsid
// Create an instance
invoke CoCreateInstance,offset clsid, NULL, CLSCTX_ALL,offset IID_IVSHelp80, offset pInterface
test eax,eax
jnz >>.NOINSTANCE
mov eax,[pInterface]
RET

.NOINSTANCE
mov eax,0
RET
ENDF

ReleaseInterface FRAME pInterface

CoInvoke(pInterface,IVSHelp80.IUnknown.Release)
RET

ENDF

SetCollection FRAME pInterface,pCollection
LOCAL wszCollection[1024]:W
LOCAL pbstrCollection:D
LOCAL pbstrNULL:D

invoke MultiByteToWideChar,CP_ACP,NULL,[pCollection],-1,offset wszCollection,1024

invoke SysAllocString,offset wszCollection
mov [pbstrCollection],eax

invoke SysAllocString,offset wszNULL
mov [pbstrNULL],eax

//SetCollection
CoInvoke(pInterface,IVSHelp80.Help.SetCollection,[pbstrCollection],[pbstrNULL])
invoke SysFreeString,[pbstrCollection]
invoke SysFreeString,[pbstrNULL]

RET
ENDF

SyncTopic FRAME pInterface, szTopic
LOCAL wszTopic[1024]:W
LOCAL pbstrTopic:D

invoke MultiByteToWideChar,CP_ACP,NULL,[szTopic],-1,offset wszTopic,1024
invoke SysAllocString,offset wszTopic
mov [pbstrTopic],eax

CoInvoke(pInterface,IVSHelp80.Help.SyncIndex,[pbstrTopic],1)
CoInvoke(pInterface,IVSHelp80.Help.Index)

invoke SysFreeString,[pbstrTopic]
RET
ENDF

ShowTopic FRAME pInterface, szTopic
LOCAL wszTopic[1024]:W
LOCAL pbstrTopic:D

invoke MultiByteToWideChar,CP_ACP,NULL,[szTopic],-1,offset wszTopic,1024
invoke SysAllocString,offset wszTopic
mov [pbstrTopic],eax

CoInvoke(pInterface,IVSHelp80.Help.DisplayTopicFromKeyword,[pbstrTopic])
CoInvoke(pInterface,IVSHelp80.Help.SyncIndex,[pbstrTopic],TRUE)

invoke SysFreeString,[pbstrTopic]
mov eax,[pInterface]
RET
ENDF
Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on January 30, 2009, 08:59:59 AM
Hello,
I am testing this (only with masm) and have differents results.
If dexplore is running,results are OK.
If dexplore isn't running,he is launched but there is no topic displayed.Dexplore isn't in his defaut configuration and windows are missing (summary,index ...)
Seems some steps are missing to launch it correctly ?.
The question is where find this steps,any idea ?.
Title: Re: Using HTMLHelp2
Post by: donkey on January 30, 2009, 09:18:12 AM
Hi ToutEnMasm,

Could be a problem in the translation or perhaps something specific about your installation, it works well here. Here is the executable for the project.



[attachment deleted by admin]
Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on January 30, 2009, 10:41:00 AM

I am using  this clsid and progid:
sIID_Help2   TEXTEQU   <{078413D2Dh,00492h,04A9Bh,{0ABh,025h,073h,006h,033h,067h,099h,077h}}>
"DExplore.AppObj.9.0"
Whis that i need to use Contents after SetCollection to make it work.
I have found the sIID with oleview.
But perhaps i make the labor more hard using this.
I will post my source code after a little experiments.


Title: Re: Using HTMLHelp2
Post by: gfalen on January 30, 2009, 10:54:52 AM
Did you know that Dexplore has a command line interface?
Run "dexplore /?" (you might need a full path)

For context help in my editor I just use ShellExecute with "dexplore.exe" as the lpFile and
"/LaunchFKeywordTopic " + current word as the lpParameters
Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on January 30, 2009, 01:30:30 PM

Hello,
I know that if in the C:\Program Files\Fichiers communs\Microsoft Shared\Help 9 path,I put a batch like that:
Quote
@echo off
dexplore /helpcol ms-help://MS.LHSMSSDK.1033 /LaunchFKeywordTopic SysAllocString
This is working perfectly.
Here is a good exercice on how using dexplore with a com interface and a progid,and without.





Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on January 30, 2009, 03:21:15 PM

Here is my best result in masm.
It's work but need Enter to search the keyword.


[attachment deleted by admin]
Title: Re: Using HTMLHelp2
Post by: donkey on January 30, 2009, 05:38:02 PM
Quote from: gfalen on January 30, 2009, 10:54:52 AM
Did you know that Dexplore has a command line interface?
Run "dexplore /?" (you might need a full path)

For context help in my editor I just use ShellExecute with "dexplore.exe" as the lpFile and
"/LaunchFKeywordTopic " + current word as the lpParameters

Hi gfalen,

Now that would be cheating ;) It is much more fun to figure out the COM interface. But seriously, the issue for me is that I am trying to figure out how to send partial keywords and have the first instance displayed, not sure if it's possible, for example passing "ExitProcess" as the keyword will not have it automatically displayed since the keyword is listed as "ExitProcess function". This is the main reason I am exploring the COM interface, also /LaunchFKeywordTopic on my system defaults to DisplayTopicFromF1Keyword which launches an internet search for the topic, this is the default behavior while DisplayTopicFromKeyword will use local help.
Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on January 30, 2009, 07:01:14 PM

Found,
At end , i have just change the searched keyword "CoInitialize" instead of "SysAllocString" and there is no need of the enter key to finish.
All is good with my source code.
Title: Re: Using HTMLHelp2
Post by: donkey on January 30, 2009, 07:33:33 PM
Hi ToutEnMasm,

This is simply the behaviour I described, if you change "SysAllocString" to "SysAllocString [AUTOMATION]" it should work as well, the topic is only displayed if there is an exact complete text match to the entry in the index and it is the only match otherwise it simply displays the first partial match in the index list and does not open the document. It demonstrates well one of the reasons I am trying the COM interface as opposed to the command line.
Title: Re: Using HTMLHelp2
Post by: gfalen on January 30, 2009, 08:01:26 PM
I only have the PSDK installed (latest one 6.1) no VCExpress or VSudio and it works every time including ExitProcess & SysAllocString.

Maybe installing one of the compilers changes something.
Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on January 31, 2009, 05:56:08 AM

To gfalen:
Problem is only with the contents of the index  (search by help2 interface).
If we search "SysAllocString",the index of the help file is written as this:
"SysAllocString [AUTOMATION]"
If we send "SysAllocString" a confirmation by the enter key is needed
if we send  "SysAllocString [AUTOMATION]" ,no confirmation is needed

Making a search in the index of the help file seems  not possible.
Used of the batch haven't this problem.

I have also the PSDK 6.1 installed and VC++ 2008 express edition.
Verify that the index is not matching exactly what you search,and if there is no need of confirmation
it works not in the same manners than for me.




Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on January 31, 2009, 06:34:05 AM

I have made a change in the code
Quote
invoke CoCreateInstance,addr clsid, NULL,CLSCTX_LOCAL_SERVER,pIID,addr ppv
With CLSCTX_ALL , dexplore.exe can stay in memory (without be visible) after the interface is released.
Title: Re: Using HTMLHelp2
Post by: donkey on February 01, 2009, 09:20:12 AM
Quote from: ToutEnMasm on January 31, 2009, 06:34:05 AM

I have made a change in the code
Quote
invoke CoCreateInstance,addr clsid, NULL,CLSCTX_LOCAL_SERVER,pIID,addr ppv
With CLSCTX_ALL , dexplore.exe can stay in memory (without be visible) after the interface is released.


I have noticed this as well but CLSCTX_LOCAL_SERVER does not seem to solve the problem reliably, since CLSTX_ALL is simply a combination of CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER and CLSCTX_LOCAL_SERVER it resolves to the same thing once CoCreateInstance discards the INPROC contexts (this type of interface cannot be instanced INPROC). The problem appears to be related (bizarrely enough) to the configuration of help searches, if you do not allow for online searches it does not terminate on release, if you allow them it will terminate. The behaviour does not seem to affect DExplore except when called via the COM interface which suggests that there is something rather large that I am missing here, I continue to scratch my head over this one....

For the problem with it not opening the help for partial matches I cheated and added a keybd_event call, however it forces us to assume that the DExplore window has the keyboard focus, I can't imagine a possibility where it wouldn't have it after a call to DisplayTopicFromKeyword but I can't definitively say a condition that it will not does not exist.

ShowTopic FRAME pInterface, szTopic
LOCAL wszTopic[1024]:W
LOCAL pbstrTopic:D

invoke MultiByteToWideChar,CP_ACP,NULL,[szTopic],-1,offset wszTopic,1024
invoke SysAllocString,offset wszTopic
mov [pbstrTopic],eax

CoInvoke(pInterface,IVSHelp80.Help.DisplayTopicFromKeyword,[pbstrTopic])

// This synchonizes the index and forces the index window to show
invoke SyncTopic,[pInterface],[szTopic]

// Show the first topic found, this is a hack but it works for now
invoke keybd_event,VK_RETURN,NULL,NULL,NULL

CoInvoke(pInterface,IVSHelp80.Help.SyncContents,[pbstrTopic])

invoke SysFreeString,[pbstrTopic]
mov eax,[pInterface]
RET
ENDF
Title: Re: Using HTMLHelp2
Post by: akane on February 01, 2009, 11:20:17 AM
I have recently created a webbrowser application with integrated PSDK help. It is able to enumerate installed namesaces, filters and topics, and ofcource extend a scintilla based IDE with F1 help system. It does not use dexplore, just the help collections.
If you have a topic with additional characters, you can query it for "ApiName" topic property, and it will return CreateProcess, CreateProcessA and CreateProcessW (click View/topic properties).
If your familiar with c++ like code, this topic may be helpful: http://www.ionicwind.com/forums/index.php/topic,2462.0.html.
I have used Microsoft Help Data Services 1.0 Type Library to create this tool.

EDIT: search in sources for CWorkerTopics::EnumNamespaces, CWorkerTopics::EnumFilters, CWorkerTopics::EnumTopics, GetTopicAttribute.
Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on February 01, 2009, 03:29:13 PM

I think i have found the soluce.
Change to Help2 (not Help) interface and there is no more problems .
I have made several tests  using the help (scrolling ...) and the help was closed at the normal time.
switch are as follow:
Quote
;  sIID_Help2   TEXTEQU   <{078413D2Dh,00492h,04A9Bh,{0ABh,025h,073h,006h,033h,067h,099h,077h}}>
    invoke GetInterfaceFromProgId,SADR("DExplore.AppObj.9.0"),addr IID_Help2

invoke CoCreateInstance,addr clsid, NULL,CLSCTX_LOCAL_SERVER,pIID,addr ppv


the "invoke keybd_event,VK_RETURN,NULL,NULL,NULL" seems to work without adding problems.
I have verify if my editor receive or not a line break when this is send.







Title: Re: Using HTMLHelp2
Post by: donkey on February 01, 2009, 05:32:14 PM
Hi,

That is the CLSID I am using and the problem persists.
Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on February 01, 2009, 06:59:48 PM

something useful for testing can be done

Quote
         @@:
         Help2 Release
         .if eax != 0
            jmp @B
         .endif

After many testing , nothing grant that the returned eax (count of interface) is = to 0.
I am certain that some (but not all) of the problems com from here.

I am writing a secure launch of dexplore as a dependant process , and then make a connection.
Hope this will solve.

Title: Re: Using HTMLHelp2
Post by: donkey on February 02, 2009, 03:47:59 AM
I have still not found a way to ensure that DExplore closes using the COM interface, as an interim solution I have modified the WaitForClose function to close it...

WaitForClose FRAME pInterface
LOCAL pint:D

mov eax,[pInterface]
mov [pint],eax

invoke CreateThread,NULL,NULL,OFFSET WaitThread,OFFSET pint,NULL,OFFSET WaitID

invoke WaitForSingleObject,eax,INFINITE

RET
ENDF

WaitThread FRAME lParam
LOCAL hwnd:D
LOCAL pid:D
LOCAL tid:D
LOCAL hProcess:D
LOCAL pInterface:D

mov eax,[lParam]
mov eax,[eax]
mov [pInterface],eax

invoke FindWindow, DExploreWndClass, NULL
mov [hwnd],eax

invoke GetWindowThreadProcessId,[hwnd],offset pid
mov [tid],eax

invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,[pid]
mov [hProcess],eax

:
invoke Sleep,125
invoke IsWindowVisible,[hwnd]
test eax,eax
jnz <

invoke ReleaseInterface,[pInterface]

invoke TerminateProcess,[hProcess],0

invoke ExitThread,0
RET
ENDF


I have put the wait for close in a thread so that in a real application with a message loop I can simply broadcast a message to tell the app it is closed, for the test I just wait for the thread to exit.
Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on February 02, 2009, 09:44:00 AM

I have found a soluce that grant that dexplore is closed
This one use a list of valid process in the computer.
TerminateProcess is called if necessary
This need just a little improvment (seems a delay is necessary before make a verify)



[attachment deleted by admin]
Title: Re: Using HTMLHelp2
Post by: gwapo on February 02, 2009, 10:54:08 AM
Hi donkey,

Sorry for the out-topic question, but what does this line means?


    jnz <  ; Jump to where?


I usually see them in most of your codes.

Thanks,

-chris
Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on February 02, 2009, 02:34:10 PM

Two modifies can be made in the securedeplore:
When no new dexplore.exe is found
Quote
         invoke IsrunningDexploreNew
         .if eax == 0
            ;no new process found,there was invisible dexplore before
            invoke MessageBox,NULL,ADDR SzNoNewProcess,ADDR SzNoNewProcessTitle,MB_YESNO
            ;invalid  the process destroy
            mov pe.th32ProcessID,0
         .endif
in the DetruireProcess PROC

Quote
DetruireProcess PROC
   Local Hprocess:dword
   mov  Hprocess,0
   mov ExitCode,0                         ;add this
                .....................



Title: Re: Using HTMLHelp2
Post by: Mark Jones on February 02, 2009, 02:45:11 PM
Quote from: gwapo on February 02, 2009, 10:54:08 AM
...what does this line mean?

    jnz <  ; Jump to where?


Hi Chris, this is one of GoASM's additional jump label syntaxes. It is like the @@: / @B / @F anonymous jump labels in MASM, except :, ., <, >, <<, and >> are used instead for various local and far meanings.
Title: Re: Using HTMLHelp2
Post by: gwapo on February 03, 2009, 06:25:46 AM
Thanks Mark  :U
Title: Re: Using HTMLHelp2
Post by: donkey on February 09, 2009, 11:53:26 AM
Still no real success with DExplore, I am considering experimenting with the MS help services interface and writing my own version of DEXplore, although there is absolutely no docs that I can find on the interface I have managed to connect, set the collection and am now trying to extract a URL for a specific keyword. It is a long process but I hope to get it done. I had hoped that the hxSession member of IVsHelp might provide me with a pointer to the IHxSession interface it is using but even though I get a valid pointer when I call it the interface seems wrong, some methods have null pointers and the stack is unbalanced after some calls, hinting that the interface is not what I was expecting. Attached is the header for MS Help Services, it appears to be the main access point for all Help2.

I have tried this, all calls return success however I still don't get a URL:

GetKeywordURL FRAME pszCollection, pszKeyword, pUrl
LOCAL wszKeyword[1024]:W
LOCAL wszCollection[1024]:W
LOCAL pbstrKeyword:D
LOCAL pOutUrl:D
LOCAL pThisSession:D
LOCAL pbstrCollection:D
LOCAL pbstrNavMoniker:D

// Create an instance of IHxSession
invoke CoCreateInstance,offset CLSID_IHxSession, NULL, CLSCTX_ALL,offset IID_IHxSession, offset pThisSession
test eax, eax
jnz >>.ERROR_NO_RELEASE

// Convert the Collection name to unicode then create a BSTR with it
invoke MultiByteToWideChar,CP_ACP,NULL,[pszCollection],-1,offset wszCollection,1024
invoke SysAllocString,offset wszCollection
mov [pbstrCollection],eax

// Set the collection
CoInvoke(pThisSession,IHxSession.Initialize,[pbstrCollection],NULL)
test eax, eax
jnz >>.ERROR_MUST_RELEASE

// Allocate an uninitialed string to return the URL
invoke SysAllocStringLen ,NULL,1024
mov [pOutUrl],eax

// Convert the keyword to unicode then create a BSTR with it
invoke MultiByteToWideChar,CP_ACP,NULL,[pszKeyword],-1,offset wszKeyword,1024
invoke SysAllocString,offset wszKeyword
mov [pbstrKeyword],eax

// Create a BSTR with the navigation moniker
invoke SysAllocString,L"!DefaultKeywordIndex"
mov [pbstrNavMoniker],eax

// Get the URL for the keyword
CoInvoke(pThisSession,IHxSession.QueryForUrl,[pbstrKeyword],[pbstrNavMoniker],0,[pbstrNULL],[pOutUrl])
test eax, eax
jnz >>.ERROR_MUST_RELEASE

// Convert the url to ANSI
invoke WideCharToMultiByte,CP_ACP,NULL,[pOutUrl],-1,[pUrl],1024,NULL,NULL

// Release the IHxSession interface
CoInvoke(pThisSession,IHxSession.IUnknown.Release)

// Free the BSTR data
invoke SysFreeString,[pbstrKeyword]
invoke SysFreeString,[pOutUrl]
invoke SysFreeString,[pbstrCollection]
invoke SysFreeString,[pbstrNavMoniker]

// Return S_OK
mov eax,NULL
RET

.ERROR_MUST_RELEASE
// Release the IHxSession interface
push eax
CoInvoke(pThisSession,IHxSession.IUnknown.Release)
pop eax

.ERROR_NO_RELEASE

RET
ENDF


If I could get the URL for a keyword it is a simple matter of displaying it in a web browser control.

[attachment deleted by admin]
Title: Re: Using HTMLHelp2
Post by: donkey on February 09, 2009, 09:13:18 PM
The levels of indirection here are mind boggling, IHxSession > IHxTopicList > IEnumHxTopic > IHxTopic > ???, Still trying to get a valid pointer to IHxTopic so I can enumerate the topics but no luck, also I think I might have to implement IMarshal in order to read/write the data for IHxSession since it doesn't seem to actually transfer any information to memory buffers in my application. If this was .NET or some extremely high level framewwork it would be a cake walk but in assembly the complexity is getting to the point where it outweighs the advantages of wrapping the interface.
Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on February 10, 2009, 01:54:08 PM
Hello,
An alternate way can be used.
Use hxcomp (visual studio sdk) to uncompiled the desired help file.
Extract the useful informations,put them in a text file.Then,before send DisplayTopicFromKeyword,search this text file and used the function with the exact index she is waiting for.
Search in text is very fast.
If necessary,I have write a tool than can extract title from multiple html page and create an index for chm file.This one can be easily modify to write just a list of keyword.


Title: Re: Using HTMLHelp2
Post by: donkey on February 10, 2009, 04:56:50 PM
Hi ToutEnMasm,

That is a solution as long as you never change your help files, and as long as you don't evr plan on using any other help collections with it, it is not the direction I am looking to take. Also what if someone is using the PSDK instead of MSDN or some other future version MS might dream up. I want general purpose wrappers for the IHxSession interface, this will allow exploits for both directly accessing a help2 data base as well as DExplore (it exposes the IDispatch interface in hxSession). I am currently looking at treating the interface as if it was an ActiveX object and calling IDispatch to execute the methods. However, to dothis I had to rewrite the header to include DSIPIDs, that will be finished soon.

Currently however, the IHxSession interface seems to be returning a bogus IDispatch since IDispatch::Invoke points to NULL, which ofcourse is completely against the rules of COM. I am still trying to figure out why, but I suspect the answer when I find it will solve all of the outstanding issues. Here's the first attempt at IDispatch::Invoke;

GetTopicURL FRAME pszCollection, pszKeyword
// Used to convert ANSI to BSTR
LOCAL wszKeyword[1024]:W
LOCAL pbstrKeyword:D
LOCAL wszCollection[1024]:W
LOCAL pbstrCollection:D

// Pointer to output BSTR
LOCAL pbstrURL:D
// Pointer to navigation moniker (always !DefaultKeywordIndex)
LOCAL pbstrNavMoniker:D

// this
LOCAL pIHxSession :D

// Used for calls to IDispatch::Invoke
LOCAL TypeInfo:D

// Empty array of named arguments
LOCAL NullPointer:D

// Array of arguments for IDispatch::Invoke
LOCAL dispparams:DISPPARAMS
LOCAL dispargs[4] :VARIANTARG

// Error returns for IDispatch::Invoke
LOCAL excpt[64]:D
LOCAL excptnum:D

// Zero the array of named arguments (there are none)
mov D[NullPointer],0

// Create an instance of IHxSession
invoke CoCreateInstance,offset CLSID_IHxSession, NULL, CLSCTX_ALL,offset IID_IHxSession, offset pIHxSession
test eax, eax
jnz >>.ERROR_NO_RELEASE

// Convert the Collection name to unicode then create a BSTR with it
invoke MultiByteToWideChar,CP_ACP,NULL,[pszCollection],-1,offset wszCollection,1024
invoke SysAllocString,offset wszCollection
mov [pbstrCollection],eax

// Set the collection
CoInvoke(pIHxSession,IHxSession.Initialize,[pbstrCollection],NULL)
test eax, eax
jnz >>.ERROR_MUST_RELEASE

// Convert the keyword to unicode then create a BSTR with it
invoke MultiByteToWideChar,CP_ACP,NULL,[pszKeyword],-1,offset wszKeyword,1024
invoke SysAllocString,offset wszKeyword
mov [pbstrKeyword],eax

// Allocate an uninitialed string to return the URL
invoke SysAllocStringLen ,NULL,1024
mov [pbstrURL],eax

// Create a BSTR with the navigation moniker
invoke SysAllocString,L"!DefaultKeywordIndex"
mov [pbstrNavMoniker],eax

// Get the typeinfo for IDispatch::Invoke call
CoInvoke(pIHxSession,IHxSession.IDispatch.GetTypeInfo,0,NULL,offset TypeInfo)
test eax,eax
jnz >>.ERROR_MUST_RELEASE_ALL

// Fill the DISPPARAMS structure, it describes the arguments array
// No named arguments
mov D[dispparams.cNamedArgs],0
// 4 arguments
mov D[dispparams.cArgs],4
// point the named arguments to an empty array
// not sure if this is necessary since there are none but can't hurt
lea eax,NullPointer
mov D[dispparams.rgdispidNamedArgs],eax

// Build the arguments array

// Store EBX
push ebx

// point EBX to our VARIANTARG array
lea ebx,dispargs
// Fill the first argument (keyword BSTR)
mov W[ebx+VARIANTARG.vt],VT_BYREF|VT_BSTR
mov eax,[pbstrKeyword]
mov [ebx+VARIANTARG.pbstrVal],eax
// Hopefully this resolves correctly, it is 16 bytes
// but I am not sure how C/C++ handles weird unions
// when it comes to structure size. The actual ammount
// of data being stored is 12 bytes (8b header + 4b data)
add ebx,SIZEOF VARIANTARG

// Fill the second argument (Navigation moniker BSTR)
mov W[ebx+VARIANTARG.vt],VT_BYREF|VT_BSTR
mov eax,[pbstrNavMoniker]
mov [ebx+VARIANTARG.pbstrVal],eax
add ebx,SIZEOF VARIANTARG

// Fill the third argument (options)
mov W[ebx+VARIANTARG.vt],VT_I4
mov D[ebx+VARIANTARG.lVal],0 ; Options
add ebx,SIZEOF VARIANTARG

// Fill the fourth argument (Filter moniker BSTR)
// this is simply a pointer to an empty BSTR
mov W[ebx+VARIANTARG.vt],VT_BYREF|VT_BSTR
mov eax,[pbstrNULL] ; FilterMoniker is NULL string
mov [ebx+VARIANTARG.pbstrVal],eax

// Resotre EBX
pop ebx

// >>>>>>> This is the GPF, IHxSession.IDispatch.Invoke points to NULL

// call IDispatch::Invoke
CoInvoke(pIHxSession,IHxSession.IDispatch.Invoke,DISPID_IHxSession_QueryForUrl,NULL,NULL,DISPATCH_METHOD,offset dispparams,[pbstrURL],offset excpt,offset excptnum)
test eax,eax
jnz >>.ERROR_MUST_RELEASE_ALL

// Free the BSTRs
invoke SysFreeString,[pbstrCollection]
invoke SysFreeString,[pbstrKeyword]
invoke SysFreeString,[pbstrURL]
invoke SysFreeString,[pbstrNavMoniker]

// Release the IHxSession interface
CoInvoke(pIHxSession,IHxSession.IUnknown.Release)
test eax,eax
jnz >>.ERROR_NO_RELEASE

// Return S_OK
xor eax,eax
RET

// each error block is framed in push/pop eax
// this is so that the return value the COM calls
// is preserved and returned by the function

.ERROR_MUST_RELEASE_ALL
push eax
// Free the BSTRs
invoke SysFreeString,[pbstrKeyword]
invoke SysFreeString,[pbstrURL]
invoke SysFreeString,[pbstrNavMoniker]
pop eax

.ERROR_MUST_RELEASE
push eax
// Free the collection BSTR
invoke SysFreeString,[pbstrCollection]
// Release the IHxSession interface
CoInvoke(pIHxSession,IHxSession.IUnknown.Release)
pop eax

.ERROR_NO_RELEASE

RET

ENDF
Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on February 10, 2009, 06:11:47 PM
Hello,
seems there is here some answers
Quote
http://kenbodensteiner.com/blog/2006/12/using-mshelp-sdk-to-access-your-mshelp.html
I will try this method getting IHxSession threw IHxIndex as suggested by the typelib



Title: Re: Using HTMLHelp2
Post by: donkey on February 10, 2009, 06:20:10 PM
Hi ToutEnMasm,

No need but thanks, in the ultimate stupid move I forgot to dereference the output BSTR pointer before sending it to WideCharToMultiByte. Once I discovered my bonehead mistake I found the interfaces acted as they should. Here is a small demo, it is not interactive but displays the help entry for WM_COMMAND, it does this without any supporting program, that is without either DExplore or H2Viewer. I have not yet found the correct syntax for wild cards but I know the methods accept them.


[attachment deleted by admin]
Title: Re: Using HTMLHelp2
Post by: donkey on February 10, 2009, 07:51:53 PM
Hi ToutEnMasm,

I had a chance to read the page you posted, an interesting approach to getting the keyword list. Here is the skeleton of an implementation in GoAsm, I didn't bother with the subtopics. There are 584,230 main topics found, no idea how many subtopics but some had 48 subtopics. For this reason I think there must be a faster way to get his information since this would on the surface be slow.

In the following code I just use a debug function to display the topic title...

BuildKeywordList FRAME hwnd, pszCollection
uses ebx
LOCAL wszCollection[1024]:W
LOCAL szTitle[1024]:B
LOCAL pThisSession:D
LOCAL pbstrCollection:D
LOCAL pbstrNavMoniker:D
LOCAL pIHxTopicList:D
LOCAL pIHxIndex:D
LOCAL count:D
LOCAL pbszLink:D

// Create an instance of IHxSession
invoke CoCreateInstance,offset CLSID_IHxSession, NULL, CLSCTX_ALL,offset IID_IHxSession, offset pThisSession
test eax, eax
jnz >>.ERROR_NO_RELEASE

// Convert the Collection name to unicode then create a BSTR with it
invoke MultiByteToWideChar,CP_ACP,NULL,[pszCollection],-1,offset wszCollection,1024
invoke SysAllocString,offset wszCollection
mov [pbstrCollection],eax

// Set the collection
CoInvoke(pThisSession,IHxSession.Initialize,[pbstrCollection],NULL)
test eax, eax
jnz >>.ERROR_MUST_RELEASE

// Create a BSTR with the navigation moniker
invoke SysAllocString,L"!DefaultKeywordIndex"
mov [pbstrNavMoniker],eax

// Allocate an uninitialed string to return the URL
invoke SysAllocStringLen ,NULL,1024
mov [pbszLink],eax

CoInvoke(pThisSession,IHxSession.GetNavigationObject,[pbstrNavMoniker],[pbstrNULL],offset pIHxIndex)
test eax, eax
jnz >>.ERROR_MUST_RELEASE_ALL

CoInvoke(pIHxIndex,IHxIndex.Count,offset count)
test eax, eax
jnz >>.ERROR_MUST_RELEASE_ALL

xor ebx,ebx
inc ebx
:
CoInvoke(pIHxIndex,IHxIndex.GetStringFromSlot,ebx,[pbszLink])
mov eax,[pbszLink]
mov eax,[eax]
invoke WideCharToMultiByte,CP_ACP,NULL,eax,-1,offset szTitle,1024,"",NULL
PrintString(szTitle)
inc ebx
cmp ebx,[count]
jl <<

invoke SysFreeString,[pbszLink]
invoke SysFreeString,[pbstrCollection]
invoke SysFreeString,[pbstrNavMoniker]


CoInvoke(pThisSession,IHxSession.IUnknown.Release)

RET

.ERROR_MUST_RELEASE_ALL
invoke SysFreeString,[pbszLink]
invoke SysFreeString,[pbstrNavMoniker]

.ERROR_MUST_RELEASE
invoke SysFreeString,[pbstrCollection]
// Release the IHxSession interface
push eax
CoInvoke(pThisSession,IHxSession.IUnknown.Release)
pop eax

.ERROR_NO_RELEASE

RET
ENDF
Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on February 10, 2009, 08:33:04 PM
Thanks,
I have found this searching in the CLSID register.
Quote
IID_IHxTreeView GUID <314111B9h,0A502h,11D2h,<0BBh,0CAh,00h,0C0h,4Fh,8Eh,0C2h,94h>>
invoke GetInterfaceFromProgId,SADR("HxVz.HxIndexCtrl.1"),addr IID_IHxTreeView
it is part of {314111BA-A502-11D2-BBCA-00C04F8EC294} microsoft help visual 1.0
This control can call The Ihx interface.
I try,without success to connect to it,perhaps did he need visual studio ?
Title: Re: Using HTMLHelp2
Post by: donkey on February 10, 2009, 09:51:57 PM
Hi ToutEnMasm,

Yes, I looked at that interface but I don't think its necessary. There is an extremely fast way of reading the topics, essentially you do the same thing but use a virtual listbox or treeview. Since the topics are extracted by an index number getting the topics to display is rather simple. It requires shifting stuff around a little bit but if I get some time tonight I will write and post the code. Filters are fairly easy to design, the moniker is in the format:

'"DocSet"="PSDK" OR "Product"="kbwindows"'

For the most part I understand and can use most of the basic interface, at least enough to display the topics list, find the keyword's URL and display it. Here's an update of the example I posted with the shifting around needed for the virtual listbox. I haven't implemented the listbox yet but I do display the first 100 topics found in a normal listbox.

[attachment deleted by admin]
Title: Re: Using HTMLHelp2
Post by: akane on February 10, 2009, 10:44:33 PM
Donkey, IHxIndex.GetStringFromSlot requires a pointer to BSTR, not a pointer to string. This method will allocate and return a BSTR.
About the tabs in topics: I have experimented with my htmlhelp-hook tool, and found that every tab should be displayed as a line-break + indent:
1. set indent to 0.
2. while you find a tab in topic text, increment the indent.
3. set listbox item to space(indent * 4) + the text AFTER the last tab.

If you click a topic in dexplore, sometimes a additional topic list pops. You can implement this by calling (see in my project CWorkerTopics::LookupKeywordUrl)
IHxTopicList *topics;
session->Query(bstrKeyword, bstrItemMoniker, HxQuery_No_Option, bstrFilterMoniker, &topics);
int NumberOfTopics;
topics->get_Count(&NumberOfTopics);

// get the topics enumerator
IEnumHxTopic *topiclist;
topics->EnumTopics(0, 0, &topiclist);


If NumberOfTopics is one, you can display it now:
HRESULT hr;
topiclist->Next(1, &topic, &hr);

BSTR bstrUrl;
topic->get_URL(&bstrUrl);


If NumberOfTopics is 2 or more, use the Next method to fill additional popup listbox.
Title: Re: Using HTMLHelp2
Post by: donkey on February 11, 2009, 12:48:08 AM
Hi akane,

I did passs it a pointer to a BSTR, I created it with SysAllocStringLen earlier in the function. The additional topics list is the list of subtopics associated with an entry, they can be found by using GetTopicsFromSlot and IHxTopic::GetInfo or IHxTopic::Title. But as I said in an earlier post I am ignoring the subtopics for the demo. However, since IHxTopicList is in itself an enumeration, there is no need to further enumerate the topics, here's the same code but with subtopics displayed (no indentation)...

BuildKeywordList FRAME hwnd, iFirst, nItems
uses ebx, edi
LOCAL pIHxTopicList:D
LOCAL count:D
LOCAL EndCount:D
LOCAL TopicCount:D
LOCAL pbszLink:D
LOCAL pbszTopic:D
LOCAL pIHxTopic:D
LOCAL pIHxTopicsList:D

invoke SendMessage,[hwnd],LB_RESETCONTENT,0,0

// Allocate an uninitialed string to return the URL
invoke SysAllocStringLen ,NULL,1024
mov [pbszLink],eax

// Allocate an uninitialed string to return the URL
invoke SysAllocStringLen ,NULL,1024
mov [pbszLink],eax

mov eax,[iFirst]
add eax,[nItems]
mov [EndCount],eax

CoInvoke(pIHxIndex,IHxIndex.Count,offset count)

test eax, eax
jnz >>.ERROR

cmp D[count],0
je >>.ERROR

// Calculate the string space needed
// Average of 64 bytes per title
invoke SendMessage,[hwnd],LB_INITSTORAGE,[count],64

mov ebx,[iFirst]
.GETTOPICS
CoInvoke(pIHxIndex,IHxIndex.GetStringFromSlot,ebx,[pbszLink])
mov eax,[pbszLink]
mov eax,[eax]
invoke SendMessageW,[hwnd],LB_ADDSTRING,0,eax
CoInvoke(pIHxIndex,IHxIndex.GetTopicsFromSlot,ebx,offset pIHxTopicsList)
CoInvoke(pIHxTopicsList,IHxTopicList.Count,offset TopicCount)
cmp D[TopicCount],2
jl >>.SHOWTOPIC
mov edi,0
inc edi
.GETSUBTOPICS
CoInvoke(pIHxTopicsList,IHxTopicList.ItemAt,edi,offset pIHxTopic)
CoInvoke(pIHxTopic,IHxTopic.Title,HxTopicGetHTMTitle,HxTopicGetTitleFileName,offset pbszTopic)
invoke SendMessageW,[hwnd],LB_ADDSTRING,0,[pbszTopic]
inc edi
cmp edi,[TopicCount]
jl <<.GETSUBTOPICS
.SHOWTOPIC
inc ebx
cmp ebx,[EndCount]
jl <<.GETTOPICS

invoke SysFreeString,[pbszLink]

xor eax,eax
RET

.ERROR
invoke SysFreeString,[pbszLink]
xor eax,eax
dec eax
RET
ENDF
Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on February 11, 2009, 02:44:35 PM
Successful connection to the help2 controls
Here is a full list of the help2 CLSID
Quote
CLSID_HxSession GUID <31411198h,0a502h,11d2h,<0bbh,0cah,00h,0c0h,4fh,8eh,0c2h,94h>>   ;HxSession Class
CLSID_HxComp GUID <314111b4h,0a502h,11d2h,<0bbh,0cah,00h,0c0h,4fh,8eh,0c2h,94h>> ;HxComp Class
CLSID_Help2_Contents_Control GUID <314111b8h,0a502h,11d2h,<0bbh,0cah,00h,0c0h,4fh,8eh,0c2h,94h>>   ;Microsoft Help 2.0 Contents Control
CLSID_Help2_Index_Control GUID <314111c6h,0a502h,11d2h,<0bbh,0cah,00h,0c0h,4fh,8eh,0c2h,94h>>   ;Microsoft Help 2.0 Index Control
CLSID_HxProtocol1 GUID <314111c7h,0a502h,11d2h,<0bbh,0cah,00h,0c0h,4fh,8eh,0c2h,94h>>   ;HxProtocol Class
CLSID_HxProtocol2 GUID <314111c9h,0a502h,11d2h,<0bbh,0cah,00h,0c0h,4fh,8eh,0c2h,94h>>   ;HxProtocol Class
CLSID_HxRegistryWalker GUID <314111f0h,0a502h,11d2h,<0bbh,0cah,00h,0c0h,4fh,8eh,0c2h,94h>>   ;HxRegistryWalker Class
CLSID_HxParseDisplayName GUID <314111f7h,0a502h,11d2h,<0bbh,0cah,00h,0c0h,4fh,8eh,0c2h,94h>>   ;HxParseDisplayName Class
CLSID_HxRegisterSession GUID <31411219h,0a502h,11d2h,<0bbh,0cah,00h,0c0h,4fh,8eh,0c2h,94h>>   ;HxRegisterSession Class
CLSID_HxRegisterProtocol1 GUID <31411228h,0a502h,11d2h,<0bbh,0cah,00h,0c0h,4fh,8eh,0c2h,94h>>   ;HxRegisterProtocol Class
CLSID_HxRegisterProtocol2 GUID <31430c59h,0bed1h,11D1h,<08Dh,0e8h,00h,0C0h,04Fh,0C2h,0E0h,0C7h>>   ;HxRegisterProtocol Class

II_D for Help2 controls  (Microsoft Help Visuals 1.0 typelib)
Quote
IID_IHxTreeView GUID <314111B9h,0A502h,11D2h,<0BBh,0CAh,00h,0C0h,4Fh,8Eh,0C2h,94h>>
IID_IHxIndexView GUID <314111C4h,0A502h,11D2h,<0BBh,0CAh,00h,0C0h,4Fh,8Eh,0C2h,94h>>

Connection with cocreateinstance,there is also a progid but connection couldn't be made with it.
This following methods works
Quote
      invoke CoCreateInstance,addr CLSID_Help2_Contents_Control,NULL,
         CLSCTX_INPROC_HANDLER OR CLSCTX_INPROC_SERVER OR CLSCTX_LOCAL_SERVER,
         addr IID_IHxTreeView,addr ppvIdispatch
      .if eax == S_OK
         invoke MessageBox,NULL,SADR("Youpi"),SADR("Contents_Control"),MB_YESNO               
         Idispatch Release
         mov ppvIdispatch,0
      .endif
      invoke CoCreateInstance,addr CLSID_Help2_Index_Control,NULL,
         CLSCTX_INPROC_HANDLER OR CLSCTX_INPROC_SERVER OR CLSCTX_LOCAL_SERVER,
         addr IID_IHxIndexView,addr ppvIdispatch
      .if eax == S_OK
         invoke MessageBox,NULL,SADR("Youpi"),SADR("Index_Control"),MB_YESNO               
         Idispatch Release
         mov ppvIdispatch,0
      .endif      

Idispatch is used here only for test
Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on February 12, 2009, 10:11:00 AM

To be complete , here is some more information and translated typelib files for masm.

The IHxSession GetNavigationObject function is a poxerful method to connect many interface.
For example:
Quote
   IHxSession Initialize,BSTR("ms-help://MS.LHSMSSDK.1033/sdkintro"),NULL
   IHxSession GetNavigationObject,BSTR("!DefaultToc"),\
            pbstrFilter,addr ppvIdispatch      
connect to the IHxHierarchy interface , How knowing that,answer is in the mssdk.hxc file

Quote
   <!-- Optional, Multiple -->
   <ItemMoniker Name="!DefaultToc" ProgId="HxDs.HxHierarchy" InitData="AnyString"/>
   <ItemMoniker Name="!DefaultFullTextSearch" ProgId="HxDs.HxFullTextSearch" InitData="AnyString"/>
   <ItemMoniker Name="!DefaultAssociativeIndex" ProgId="HxDs.HxIndex" InitData="A"/>   
   <ItemMoniker Name="!DefaultKeywordIndex" ProgId="HxDs.HxIndex" InitData="K"/>
   <ItemMoniker Name="!DefaultContextWindowIndex" ProgId="HxDs.HxIndex" InitData="F"/>
   <ItemMoniker Name="!DefaultDynamicLinkIndex"   ProgId="HxDs.HxIndex" InitData="B" />
   <ItemMoniker Name="!DefaultNamedUrlIndex" ProgId="HxDs.HxIndex" InitData="MSSDK_NamedUrl"/>
   <ItemMoniker Name="!SampleInfo" ProgId="HxDS.HxSampleCollection" InitData="AnyString"/>
There is just to change the chain beginning by a "!" in the GetNavigationObject function and you got the interface.


[attachment deleted by admin]
Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on February 13, 2009, 11:50:56 AM
After all this research,here is a sample.
He search Help index of the SDK (6.1),take the first he found,get the url of this index and send it to the internet explorer itself.
There is no use of dll or windows to make all that.He used the IWebBrowser2 interface.
Notes:
Take care with BSTR = pointer and BSTR* pURL = pointer on pointer
Some macro can interpret "!" as an operator see SADR macro to know how avoid this
All is written for masm,and the executable will work immediately if you have the sdk.If not modify the namespace.
Quote
   ;NameSpace = "ms-help://MS.LHSMSSDK.1033/sdkintro"
   IHxSession Initialize,BSTR("ms-help://MS.LHSMSSDK.1033/sdkintro"),NULL




[attachment deleted by admin]
Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on March 05, 2009, 07:26:02 PM
Hello,
There is one thing to know for initiate and uninitiate Help2 and dexplore.exe.
They are independant.
To close all ,two things must be made.
Quote
            Help2  Close         
            Help2 Release
If "Help2  Close" isn't call,dexplore stay invisible in memory,and must be closed with the task manager.
The help2 interface create a new Instance of dexplore when we call the first function using it.
To avoid mutiples Instances of dexplore when there is multiple callers,the interface pointer can be pass creating a new message with RegisterWindowMessage.
I am testing this.



Title: Re: Using HTMLHelp2
Post by: ToutEnMasm on March 06, 2009, 05:40:49 PM
The good maner to get the default collection with Help2
Quote
Help2 Collection,addr BSTRanswer
This give the last collection used.
A little sample  is join to play with.
You have to find the good order to make it work.
In case of multiple callers,a dll is needed,to avoid multiple dexplore in memory.
Some errors (manual translate) must be corrected in the source.  :green2
Just replace the old text by this one
Quote
   STHelp2   STRUCT
      QueryInterface                  comethod3 ?
      AddRef                          comethod1 ?
      Release                         comethod1 ?
      GetTypeInfoCount                comethod2 ?
      GetTypeInfo                     comethod4 ?
      GetIDsOfNames                   comethod6 ?
      invoke1                         comethod9 ?   
      ;---- end Idispatch ----------------------      
      Contents                        comethod1 ?
      Index                           comethod1 ?
      Search                          comethod1 ?
      IndexResults                    comethod1 ?
      SearchResults                   comethod1 ?
      DisplayTopicFromId              comethod3 ?
      DisplayTopicFromURL             comethod2 ?
      DisplayTopicFromURLEx           comethod3 ?
      DisplayTopicFromKeyword         comethod2 ?
      DisplayTopicFromF1Keyword       comethod2 ?
      DisplayTopicFrom_OLD_Help       comethod3 ?
      SyncContents                    comethod2 ?
      CanSyncContents                 comethod2 ?
      GetNextTopic                    comethod3 ?
      GetPrevTopic                    comethod3 ?
      FilterUI                        comethod1 ?
      CanShowFilterUI                 comethod1 ?
      Close                           comethod1 ?
      SyncIndex                       comethod3 ?
      SetCollection                   comethod3 ?
      Collection                      comethod2 ?
      Filterout                       comethod2 ?
      Filterin                        comethod2 ?
      FilterQuery                     comethod2 ?
      HelpOwnerout                    comethod2 ?
      HelpOwnerin                     comethod2 ?
      HxSession                       comethod2 ?         ;IDispatch** ppObj
      Help                            comethod2 ?         ;IDispatch** ppObj
      GetObject1                      comethod4 ?
      ;-------- 9.0----------------------------
      SearchEx                        comethod4 ?
      HowDoI                          comethod1 ?
      Favorites                       comethod1 ?
      AskAQuestion                    comethod2 ?
      DisplayTopicFromURLEx2          comethod4 ?
      InitializeSettingsToken         comethod2 ?      
   STHelp2   ENDS




[attachment deleted by admin]