News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Using HTMLHelp2 with DExplore

Started by donkey, January 30, 2009, 02:16:37 AM

Previous topic - Next topic

ToutEnMasm


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.








donkey

Hi,

That is the CLSID I am using and the problem persists.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

ToutEnMasm


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.


donkey

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.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

ToutEnMasm


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]

gwapo

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

ToutEnMasm


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
                .....................




Mark Jones

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.
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

gwapo


donkey

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]
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

donkey

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.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

ToutEnMasm

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.



donkey

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
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

ToutEnMasm

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




donkey

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]
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable