Use compilation to access COM objects

zhaozj2021-02-16  50

Use compilation to access COM objects

Ernest murphy ernie@surfree.com

Revised DEC 26 2000 for Inclusion As Part of Masm32

Revised July 10 2000 for The New Form of Coinvoke.

Sample Code for this article is available at ... / COM / EXAMPLES / SHORTCUT

Abstract:

principle:

The COM (Component Object Model) is used by the Windows operation system in increasing ways. For example, the shell.dll uses COM to access some of its API methods. The IShellLink and IPersistFile interfaces of the shell32.dll will be demonstrated to create A Shortcut Shell Link. a Basic Understanding of COM is Assumed. The code Sample Included is Masm Specific.

COM (Component Object Model) is increasingly used by the Windows operating system. For example, shell.dll uses COM to access some of its own API functions. Shell32.dll's ISHELLLINK and IPERSISTFILE interface will be used to demonstrate how to create a shortcut. The basic understanding of COM is desirable. The sample code included is MASM is dedicated.

Introduction:

preface:

COM may seem complicated with it's numerous details, but in use these complications disappear into simple function calls. The hardest part is understanding the data structures involved so you can define the interfaces. I apologize for all the C terminology used in here. While COM is Implementation neutral, IT Borrows Much Terminology from C To Define Itself.

COM may look complicated due to its numerous details, but these complex factors disappeared in a simple function call in actual use. The most difficult part is to understand the data structure in which it is used, knowing it you can define the interface (Interfaces). I am sorry for the C terminology used here. Although COM is implemented as neutral, it borrows many terms from C to define itself.

In order to use the COM methods of some object, you must first instance or create that object from its coclass, then ask it to return you a pointer to it's interface. This process is performed by the API function CoCreateInstance. When you are done with Take You Call it's release method, and card and the coclass will take the coclass. In order to use some object's COM function (Method), you must first analyze according to its CoClass (exemplary) Or create this object. When you run out this interface, you call its Release function, COM, CoClass will process the delete object and the task of uninstalling CoClass.

A com object is refered to as the server. The program................

COM objects are called Server. Calling a COM object is called a client (customer)

Assessing COM METHODS

Access COM function

To use COM methods you need to know before hand what the interface looks like. Even if you "late bind" through an IDispatch interface, you still need to know what IDispatch looks like. A COM interface is just table of pointers to functions. Let's start with the IUnknown interface. If you were to create a component that simply exports the IUnknown interface, you have a fully functional COM object (albeit on the level of "Hello World"). IUnknown has the 3 basic methods of every interface, since All Interfaces inherit from iunknown. Keep in Mind All An Interface Consists of Is A Structure of Function Pointers. For iunknown, IT Looks Like this:

In order to use a COM function you need to know the image of the interface in advance. Even if you "dynamically bind" through a IDispatch interface, you still need to know the look of Idispatch. A COM interface is a form of a function pointer. Let us start from the iUnknown interface. If you want to create a component that is only exported (Export) iUnknown interface, you will get a perfect COM object (although just at the "Hello World" level). Each interface has three basic functions of iUnknown because all interfaces are inherited from iUnknown. Always remember that all interfaces are structures containing a function pointer. For iUnknown, it looks like this: IUNKNOWN STRUCT DWORD

IUnknown methods

IUNKNOWN_QUERYINTERFACE QUERYINTERFACE_POINTER?

IUNKNOWN_ADDREF ADDREF_POINTER?

IUNKNOWN_RELEASE RELEASE_POINTER?

Iunknown Ends

That's it, just 12 bytes long. It holds 3 DWORD pointers to the procedures that actually implement the methods. It is the infamous "vtable" you may have heard of. The pointers are defined as such so we can have MASM do some type checking For US WHEN Compiling Our Calls. Since The VTable Holds The Addresses of functions, or Pointers, these Pointers Are TypedEfed IN Our Interface Definition As Su:

This is it, only 12 bytes long. It holds 3 pointers of three double-word size (DWORD), pointing to the actual implementation. It is the unfamous "vTable" you may have heard. The pointer is defined as follows, making MASMs to make some types of type checking when compiling our calls. Since VTABLE saves the address of the function, or the pointer, these pointers are defined in our interface definition:

Queryinterface_pointer typef PTR Queryinterface_Proto

AddRef_Pointer TypedEf PTR AddRef_Proto

Release_pointer typef PTR Release_Proto

Finally, WE Define The Function Prototypes as FultoWS:

Finally, we define the function prototype:

QueryInterface_proto typedef proto: dword,: dword,: DWORD

AddRef_Pointer TypedEf Proto: DWORD

Release_pointer TypedEf Proto: DWORD

In keeping with the MASM32 practice of "loose" type checking, function parameters are just defined as DWORDs. Lots of work to set things up, but it does keeps lots of errors confined to compile time, not run time. In practice, we will Wrap Up The Interface Definitions in Include Files and Keep The from Clustering Up The Source Code. In order to keep the MASM32's "loose" type check, the function parameters are only defined as DWORD. In order to make things to make a lot of work, it does limit many errors in the compile period, not at runtime. In principle, we have to put these interface definitions in the included file, avoiding them in the source code.

One rather big compilation on defining an interface: MASM can not resolve forward references like this, so we have to define them backwards, by defining the function prototype typedefs first, and the interface table last The include files for the example program later on defines the. Interfaces this way.

When defining a big problem with an interface: MASM cannot resolution (resolve) like this forward reference, so we must define them later, first define the function prototype, define the interface table (Interface Table). The included files of the later sample programs are defined in this way.

TO ACTUALLY USE An Interface, You NEED A POINTER TO IT.

In order to actually use an interface, you need a pointer to it.

The CoCreateInstance API can be used to return us this indirect pointer to an interface structure It is one level removed from the vtable itself, and actually points to the "object" that holds the interface The final structure looks like this:.. CoCreateInstance

The API can be used to return indirect points to a pointer to an interface structure. It removes a level from the vTable itself, and it is actually pointing to an "object", which saves the interface. The final structure is this mode:

THERE IS A LOT OF INDIRECTION USING THIS STRUCTURE, IT CAN Drive You Batty Trying to Write Code To Properly Reference And De-Reference There Elements. Macros to Simplify This Task Will Be defined.

Using this structure, there are many indirects, if you try to write code to properly reference (de-reference), it will crazy. Will define some macro to simplify such work.

When the client makes a call to the COM library to create a COM object, it passes in the address where it wants the object pointer to be placed. This initial pointer is generically referred to as "ppv," from the C speak "pointer to pointer to (void), "where (void) means an unspecified type. It holds the address of another pointer (" pv "), and this pointer refers to a whole table of pointers, one table entry for each function of the interface. When the user calls the COM library to create a COM object, it passes an address in which the object is saved. This initial pointer is generally referred to as "PPV", from C 's point of view, "pointing pointer to the pointer to the VOID type", where Void means an unspecified type. It saves the address of another pointer ("PV"), and that pointer points to a full pointer table, which corresponds to a function in an interface with a table item.

For example, say we used CoCreateInstance and successfully got an interface pointer ppv, and wanted to see if it supports some other interface. We can call its QueryInterface method and request a new ppv (ppv2, pointer to an Interface) to the other interface ( PIID, POINTER TO A Interface Identifying GUID WE Are Interested In. In C, Queryinterface Has A Prototype That Would Look Like SO:

For example, we successfully obtain an interface pointer PPV with CocreateInstance, and want to see if it supports some interfaces. We can call it QueryInterface function to request a new PPV (PIID, PPV2, a pointer) of the interface (PIID, interface pointer ID GUID) to other we are interested in. With C, QueryInterface has a prototype:

(HRESULT) SomeObject :: Queryinterface (this: POBJECT, IID: Pguid, PPV2: Pinterface)

Such a Call Would Would Look Like THIS:

Such a call is to do this:

Get Pointer to the Object

MOV EAX, PPV

And use it to find the interface structure

Mov Edx, [EAX]

; push the function parameters Onto the stack

Push Offset PPV2

Push Offset IID_ISOMEOTHERINTERFACE

Push DWORD PPV

; and the Call That Method

Call DWORD PTR [EAX 0]

This May Be Accomplished Using The Built-in Masm 'Invoke' Macro As Such: This can be done using the "Invoke" macro built by MASM, just like this:

Get Pointer to the Object

MOV EAX, PPV

And use it to find the interface structure

Mov Edx, [EAX]

; and the Call That Method

Invoke (IUNKNOWN PTR [EDX]). IUNKNOWN_QUERYINTERFACE, PPV,

AddR IID_SOMEOTHERINTERFACE, AddR PPV_New

I Hope you find this as wonderfully Simple as I do.

I hope that you can find these quite simple as I am.

Note We Must Pass in The Pointer We buy, this lets the interface know which object (literall "this" object) We are for.

Note that we must pass the pointers we use, which makes the interface know which object (strictly said, "this" object) we are using.

Note the register must be type cast (IUnknown PTR [edx]). This lets the compiler know what structure to use to get the correct offset in the vtable for the .QueryInterface function (in this case it means an offset of zero from [edx ]). Actually, The Information Contading by The Interface Name and Function Name Called Disappear At Compile Time, All That Is Left Is A Numeric Offset from an as of yet value unspecified pointer.

Note that the register must be converted to the type (IUNKNOWN PTR [EDX]). This allows the compiler to know what structure is used in the VTABLE of the QueryInterface function (in this case, it is 0 offset position starting from [EDX]). In fact, the information contained by the interface name and function name disappears when compiling, and all remaining is a digital offset position starting from one pointer that has not yet specified values.

One more semi-obscure point. Notice I changed the interface method name from simply "QueryInterface" to "IUnknown_QueryInterface". This is a bit of name decoration I've found necessary. When you get to larger COM projects with many similar interfaces you will Run Into a Problem, That Is Different Interfaces With Identical Method Names. This Is Quite Valid, In Fact It's Called Polymorphism, But Can Confuse The Compiler A bit.

Another place where some is unknown. Note that I change the interface function name from the simple "queryinterface" to "iUnknown_queryinterface". This is what I found to be decorated. When you want a big COM project, it has many interfaces that may make you trouble. That is, different interfaces have the same function name. This is absolutely effective, in fact it is called polymorphism, but may make the compiler do not understand. Without this name decoration scheme things will be safe until you have two different interfaces with identical method names but different parameters to that method. This is more common then you might first think, but just consider how many interfaces might have a PRINT method.

Don't join the name decoration, things are still safe before you encounter such two different interfaces, they contain the same function name but the parameters are different. This situation is more common than you think, as long as you think how many interfaces may have a Print function.

The Coinvoke Macro

COINVOKE macro

WE CAN SIMPLIFY a COM INVOKE FURTHER WITH MACRO. This Coinvoke Macro is Part of The OAIDL.INC FILE.

We can further simplify COM calls through macros. This CoinVoke Macro is part of the OAIDL.inc file.

; ------------------------------------------------- --------------------

COINVOKE MACRO

;

Invokes an Arbitrary COM Interface

;

; Revised 12/29/00 to Check for Edx AS A param and force compiration error

THANKS to andY Car for a how-to suggestion

; Revised 7/18/00 to Pass Pointer in Edx (Not Eax) To Avoid Confusion with

Parmas Passed with addr (jeremy collake's excellent suggestion)

; Revised 5/4/00 for MEMBER FUNCTION NAME DECORATION

See http://ourworld.compuserve.com/homepages/ernies_world/coinvoke.htm

;

; Pinterface Pointer to a specific interface instance. INSTANCE

; Interface The interface's struct typedef

Function Which Function or Method of The Interface To Perform

args all required arguments

(Type, Kind and Count Determined by the function)

;

COINVOKE MACRO PINTERFACE: Req, Interface: Req, Function: Req, Args: vararg

Local istate, Arg

For arg,

;; Run thru args to see reason edx is lurking in thereifidni <& arg>,

.

ENDIF

ENDM

iStatement catstr

, <_>, <& Function, pinterface>

IFNB

; Add the list of parameter arguments if any

iStatement Catstr istate, <,>, <& args>

ENDIF

Mov Edx, Pinterface

Mov Edx, [EDX]

Istatement

ENDM

; ------------------------------------------------- --------------------

Thus, The Same Queryinterface Method As Before Can Be Invoked In A Single Line:

Therefore, and the previous QueryInterface function can be called by one line:

Coinvoke PPV, IUNKNOWN, Queryinterface, Addr IID_SOMEOTHERFACE, ADDR PPNEW

Note That now the name decoration is doe for us by the macro.

Note that the same name decoration is completed by macro for us.

The only 'gotcha' (well, the most obvious) is that no parameters to a COM call should be passed in edx as this register is used to handle 'this' the object reference. Using edx as a parameter will generate a compile error.

The only trouble (oh, the most obvious) is the parameter that calls COM, cannot be passed by EDX because this register is used to handle the THIS of the object. Use EDX as a parameter to generate a compilation error.

Using ishellfile and ipersistfile from shell32.dll

Use shell32.dll in Ishellfile and IPERSISTFILE

The shell32.dll provides a simple. Easy way to make shell links (shortcuts). However, it uses a COM interface to provide this service. The sample below is based on the MSDN "Shell Links" section for "Internet Tools and Technologies. "

Shell32.dll provides a simple and easy way to create shortcuts. However, it uses the COM interface to provide this service. The following example is based on the "Shell Links" section of "Internet Tools and Technology" "in the MSDN.

This May Be a strange place to find documentation, but there is.

This may be a strange place to find the document, but it is there.

The "shell links" Article May Be Found At: http://msdn.microsoft.com/library/psdk/shellcc/shell/shortcut.htm

"Shell Links" articles can be found at http://msdn.microsoft.com/library/psdk/shellcc/shell/shortcut.htm. For this tutorial we will access the following members of the IShellLink and the IPersistFile interfaces. Note every interface includes a "ppi" interface parameter, this is the interface that we calling to (it is the THIS parameter). (The following interface information is A Copy of Information Published by Microsoft

In this tutorial, we will access members of the two interfaces of IshellLink and IPersistFile. Note that each interface includes a "PPI" interface parameter, this is a pointer we are calling (it is the THIS). (The following interface information is replicated by Microsoft's information)

Ishelllink :: Queryinterface, PPI, AddR Riid, AddR PPV

* RIID: The Identifier of The Interface Requested. To Get Access To The THE

* PPV: The Pointer to The Variable That Receives The Interface.

Description: Checks if the object also supports the Requested Interface. If SO,

Signs The PPV Pointer with the interface's pointer.

Ishelllink :: Release, PPI

Description: Decrements The Reference Count On The IsHelllink Interface.

Ishelllink :: setPath, PPI, Addr Szfile

* pszfile: a Pointer to a Text Buffer Containing The New Path for the shell

Link Object.

Description: Defines where the file the shell link points.

Ishelllink :: SeticonLocation, PPI, Addr SizConpath, Iicon

* psziconpath: a Pointer to a Text Buffer Containing the New icon path.

* IICON: an index to the icon. This index is zero based.

Description: Sets Which icon the shellink will.

IPERSISTFILE :: Save, PPI, Addr SzfileName, Fremember

* pszfilename: Points to a Zero-Terminated string containing the Absolute Path

Of the file to which the Object shouth be saved.

* Fremember: INDICATES WHETHER THE PSZFILENAME PARAMETER IS To BE Used As The

Current Working File. if true, pszfilename becomes the current file and theobject shouth ip. if false, this Save

Operation is a "save a copy as ..." Operation. in this case, The Current File

Is Unchanged and The Object Should Not Clear ITS Dirty Flag. if PszFileName IS

NULL, The Implementation SHOULD IGNORE The Fremember Flag.

Description: Perform A Save Operation for the shelllink object, or saves the shell link area.

IPERSISTFILE :: Release, PPI

Description: Decrements The Reference Count On The IPersistFile Interface.

............... ..

These interfaces contain more functions than this (refer to the interface definition in the following code), but we only need to pay attention to the few of us will actually use.

A shell link is the ms-speak name for a shortcut icon. The information contained in a link (.lnk) File IS:

Shell Link is a shortcut Microsoft. The information contained in a link (.lnk) file is:

1 - The file path and name of the program to shell 2 -.. Where to obtain the icon to display for the shortcut (usually from the executable itself), and which icon in that file to use We will use the first icon in the File 3 - A File path and name where the shrortcut shouth be stored. 1 - Path and Name Pointing. 2 - Shortcuts The path to the icon (usually the execution file itself), and which icon in the file. We will use the first icon of the file. 3 - Shortcuts should be stored in the file path and the name.

The Use of these Interfaces IS Simple and StraightForward. It goes like this:

The usage of these interfaces is quite simple. The whole process is like this:

Call CocreateInstance CLSID_SHELLLINK for A IID_ID_ISHELLLINK Interface

Call CoCreateInstance CLSID_SHELLLINK Get a IID_ISHELLLINK interface queryinterface ishelllink for an iid_ipeistfile interface.

QueryInterface ishelllink gets the IID_IPERSISTFILE interface.

Call ishelllink.setPath To Specify WHERE The Shortcut Target IS Calls ishellLink.SetPath to specify the target pointing to the shortcut.

Call ishelllink.seticonlocation to Specify Which icon to use

Call iShellLink.seticonLocation to specify which icon used.

Call ipersistfile.save to save our new shortcut .llnk file.

Call ipersistfile.save to save our new shortcut .lnk file.

Finally,

At last

Call ipersistfile.release

Call iPersistFile.Release

Call ishelllink.release

Call ishelllink.release

This releases our hold on these interfaces, which will automatically lead to the dll that supplied them being unloaded. Again, the hard part in this application was finding documentation. What finally found broke the search open was using Visual Studio "Search in Files" to Find "IshellLink" and "IPERSISTFILE" in the / include area of ​​msvc. this Lead me to various .h Files, from Which I Hand Translated The Interfaces from C to Masm.

This releases our saved interface. This will automatically uninstall the DLL that provides their DLL. In addition, the most difficult part in the process is to find a document. The final breaking is looking for "ISHELLLLINK" and "iPersistFile" in the MSVC's INCLUDE directory in the MSVC in the "ISHELLLINK" in the MSVC's "IPERSISTFILE" in the IPERSTFILE. This leads to several .h files, where I hand define the interface from C to MASM.

Another handy tool I could have used is the command line app "FindGUID.exe," which looks through the registry for a specific interface name or coclass, or will output a list of every class and interface with their associated GUIDs.

Another convenient tool I use is the command line program "Findguid.exe", which looks up a specified interface name or CoClass, or outputs each class and interface and the GUID they associated.

Finally, The Oleview.exe Application Will Let You Browse The Registry Type Libraries and Mine Them For Information. However, These Tools com with msvc and isprietary.

Finally, the OLEVIEW.EXE program allows you to browse the type library of the registry and dig out the information. However, this tool is sold with MSVC, which is copyrighted.

Take care when defining an interface. Missing vtable methods lead to strange results. Essentially COM calls, on one level, amount to "perform function (number)" calls. Leave a method out of the vtable definition and you call the wrong interface. The original IShellLink interface definition I used from a inc file I downloaded had a missing function. The calls I made generated a "SUCCEEDED" hResult, but in some cases would not properly clean the stack (since my push count did not match the invoked function's pop Count, Thus Lead to a GPF AS I Exited A Procedure. Keep this in mind if you elry get similar "Weird" Results. Be careful when defining an interface. The function of missing the VTABLE causing strange results. In essence COM call, from one level, it is equivalent to "executing function (number)". Put a function delete the definition of VTABLE, causing you to call the wrong interface. The initial definition of the ISHELLINK interface I used is from a downloaded INC file, which has little function. I made the call generated "succeeded" HRESULT, but in some cases, it may not be a normally clear stack (because my PUSH's number of push does not match the number of POPs of the called function), so I have an exit one function. The time causes GPF. Keep in mind this when you get similar "singular" results.

Makelink.asm, A Demonstration of COM

A demo of makelink.asm, com

This program does very little, as a good tutorial program should. When run, it creates a shortcut to itself, in the same directory. It can be amusing to run from file explorer and watch the shortcut appear. Then you can try the shortcut and Watch it's cree level.

This program doesn't have much thing, just like a good tutorial should work. After running, it created a shortcut to your own in the same directory. It may be interesting to run and observe shortcuts in the file manager. Then you can try a shortcut and see that its creation time has changed.

THE SHELL LINK TUTORIAL CODE IN ... / COM / EXAMPLES / SHORTCUT. IT Begins with Some "Hack Code" to get the ful File Name path of the executable, and also makes a string with the size path That change "Shortcut to shelllink.lnk" these Strings Are Passed to the shell link interface, and it is enough). Sample code of shortcut is ... / COM / Examples / Shortcut. It is started from "Hack Code" that starts with the full path of the file name of the executable file name, and a string is created with the same path. It changes the file to "Shortcut to shellLink.lnk". These strings are passed to the Shell Link interface, and it is saved (the language of COM is persisted).

THE COCREATELINK PROCEDURE Used to Actually Perform The Com Methods and Perform This Link Creation Has Been Kept As General As Possible, And May Have Reuse Possibilities in Other Applications.

The CocreateLink function used to actually perform COM functions and implementation shortcuts is designed to be as common as possible, so it may be possible in other programs.

This program is similar to earlier published tutorial, but has been edited for some additional clarity. The interfaces are defined in a separate include file to reduce clutter. It may be built in MASM32 by using the ... / COM / bin / BLDDLL. Bat file support.

This procedure and the earlier tutorial are very similar, but for more clear and re-editing. In order to avoid the chaotic interface to be defined in a separate container file. It can be created by using the provided ... / COM / BIN / BLDLL.BAT file.

Additional note: Iczelion has quite a useful file in his tutorials named resource.h It is quite useful when using rc.exe to compile resource files I use it so much I have moved it to my / masm32 / include / folder You... NEED TO Either Move your copy there, or change the path in the rsrc.rc file to build it profilely.

Additional description: ICZelion has a quite useful file called resource.h in its tutorial. This is quite useful when using rc.exe to compile the resource file. I used it too frequently to move it to my / masm32 / include folder. You need to move your copy to it, or change the path in the RSRC.rc file, make it possible to create it.

BIBLIOGRAPHY:

bibliography:

"INSIDE COM, Microsoft's Component Object Model" Dale Rogerson Copyright 1997, Paperback - 376 Pages CD-ROM Edition

Microsoft Press; ISBN: 1572313498

(The Book for Understanding How CoM Works on a Fundamental Level. Uses C Code to Illustrate Basic Concepts As It Builds Simple Functional COM Object)

"Automation Programmer's Reference: Using ActiveX Technology To Create

Programmable Applications (No Author Listed)

CopyRight 1997,

Paperback - 450 Pages

Microsoft Press; ISBN: 1572315849

(This book has been available online on MSDN in the past, but it is cheap enough for those of you who prefer real books you can hold in your hand. Defines the practical interfaces and functions that the automation libraries provide you, but is more of A Reference Book Ten A "User's Guide")

Microsoft Developers Network

http://msdn.microsoft.com/

"Professional Visual C 5 ActiveX / COM Control Programming" Sing Li and Panos Economopoulos

Copyright April 1997,

PaperBack - 500 Pages (No CD ROM, Files Available Online)

Wrox press inc; ISBN: 1861000375

(Excellent description of activeX control and control site interfaces. A recent review of this book on Amazon.com stated "These guys are the type that want to rewrite the world's entire software base in assembler." Need I say more?)

"Sean's Inconsequential Homepage" http://ript.net/~spec/

Various hardcore articles on low-level com and attl techniques. Coded in C

"Using COM in Assembly Language" Bill Tyler

http://thunder.prohosting.com/~asm1/

Assembly Language Journal, APR-JUNE 99

Code

Makelink.asm

; ------------------------------------------------- --------------------

Makelink.asm ActiveX Simple Client To Demonstrate Basic Concepts; Written & (C) Copyright April 5, 2000 by Ernest Murphy

;

Contact the author at ernie@surfree.com

;

May Be Reuse for Any EduCational OR

Non-Commercial Application without Further License

; ------------------------------------------------- --------------------

.386

.Model flat, stdcall

Option CaseMAP: NONE

INCLUDE /MASM32/INCLUDE/Windows.inc

INCLUDE /MASM32/INCLUDE/USER32.INC

INCLUDE /MASM32/INCLUDE / WANEL32.INC

INCLUDE /MASM32/INCLUDE/ole32.inc

INCLUDE /MASM32/COM/include/oaidl.inc

INCLUDE /MASM32/COM/include/shlobj.inc

INCLUDELIB /MASM32/LIB/USER32.LIB

INCLUDELIB /MASM32/LIB/kernel32.lib

INCLUDELIB /MASM32/LIB/ole32.lib

; ------------------------------------------------- --------------------

Cocreatelink Proto: DWORD,: DWORD

MakeMessage Macro Text: REQ

; Macro To Display a Message Box

; TEXT to DISPLAY IS Kept Local TO

THIS ROUTINE for Ease of Use

Local LBL

Local sztext

JMP LBL

SzText:

DB text, 0

LBL:

Invoke Messagebox, Null, Sztext, Addr Szappname, MB_OK

ENDM

; IPERSISTFILE INTERFACE

IPERSISTFILE STRUCT DWORD

IPERSISTFILE_QUERYINTERFACE COMETHOD3?

IPERSISTFILE_ADDREF COMETHOD1?

IPERSISTFILE_RELEASE COMETHOD1?

IPERSISTFILE_GETCLASSID COMETHOD2?

IPERSISTFILE_ISDIRTY COMETHOD1?

IPERSISTFILE_LOAD3?

IPERSISTFILE_SAVE COMETHOD3?

IPERSISTFILE_SAVOMPLETED COMETHOD2?

IPERSISTFILE_GETCURFILE COMETHOD2?

IPERSISTFILE ENDS

; ------------------------------------------------- --------------------.Data

Szappname byte "shell link maker", 0

SzlinkName Byte "Shortcut to Makelink.Lnk", 0

SZBkslash Byte "/", 0

Hinstance Hinstance?

POS DWORD?

SZBuffer1 Byte Max_path Dup (?)

SZBuffer2 Byte Max_path Dup (?)

; ------------------------------------------------- --------------------

.code

Start:

; ------------------------------------------------- --------------------

; this bracketed code is Just A 'Quick Hack'

To Replace the filename from the filepathname

; with the 'Shortcut to' Title

;

Invoke getModuleHandle, NULL

Mov Hinstance, EAX

Invoke GetModuleFileName, Null, Addr Szbuffer1, Max_Path

Invoke Lstrcpy, Addr Szbuffer2, Addr Szbuffer1

Find the last baccheslash '/' and change it to zero

Mov Edx, Offset Szbuffer2

MOV ECX, EDX

.Repeat

Mov Al, Byte Ptr [EDX]

.IF AL == 92; "/"

MOV ECX, EDX

.Endif

Inc EDX

.Until al == 0

MOV Byte PTR [ECX 1], 0

Invoke Lstrcpy, Addr Szbuffer2, Addr Szlinkname

; ------------------------------------------------- --------------------

Here is where we call the proc with the com mathods

Invoke Coinitialize, NULL

MakeMessage "Let's Try Our Createlink."

Invoke Cocreatelink, Addr Szbuffer1, Addr Szbuffer2

MakeMessage "That's all folks !!!"

INVOKE Couninitialize

Invoke EXITPROCESS, NULL

; ------------------------------------------------- --------------------

Cocreatelink Proc Pszpathobj: DWORD, PSZPATHLINK: DWORD

Createlink - Uses the shell's ishelllink and ipersistfile interface

To create and store a shortcut to the specified object .; returns the hresult of calling the member functions of the interface.

Pszpathobj - Address of a buffer containing the path of the object.

PSZPATHLINK - Address of a buffer containing the path where the po

Shell Link is to be stored.

Adapted from Msdn Article "Shell Links"

Deleded Useless "Description" Method

Added Set icon LocationMETHOD

Local PWSZ: DWORD

Local PSL: DWORD

Local PPF: DWORD

Local HRESULT: DWORD

Local Hheap: DWORD

.DATA

CLSID_SHELLLINK GUID SCLSID_SHELLLINK

IID_ISHELLLINK GUID SIID_ISHELLLINK

IID_IPERSISTFILE GUID {00000010BH, 00000H, 00000H, / /

{0C0H, 000H, 000H, 000H, 000H, 000H, 000H, 046H}}

.code

First, Get Some Heap for A Wide Buffer

Invoke getProcessHeap

Mov Hheap, EAX

Invoke Heapalloc, HHEAP, NULL, MAX_PATH * 2

MOV PWSZ, EAX

Get a Pointer to the ishelllink interface.

Invoke CocreateInstance, AddR CLSID_SHELLLINK, NULL,

CLSCTX_INPROC_SERVER,

AddR IID_ISHELLLINK, AddR PSL

Mov HRESULT, EAX

Test Eax, EAX

.IF successEDEDED

Query IshellLink for the IPersistfile

; Interface for Saving the Shortcut

Coinvoke PSL, ISHELLLINK, Queryinterface, Addr IID_IPERSISTFILE, ADDR PPF

Mov HRESULT, EAX

Test Eax, EAX

.IF successEDEDED

; Set the path to the shortcut target

Coinvoke PSL, ISHELLLINK, SETPATH, PSZPATHOBJ

Mov HRESULT, EAX

Add The Description, Use First Icon Found

Coinvoke PSL, Ishelllink, SeticonLocation, Pszpathobj, 0

Mov HRESULT, EAX

Change string to unicode.

COM TYPICALLY EXPECTS Unicode Strings

Invoke MultibyToWideChar, CP_ACP, 0, PSZPATHLINK,

-1, Pwsz, Max_Path

Save the link by calling ipersistfile :: save

Coinvoke PPF, IPERSISTFILE, Save, Pwsz, Truemov Eax, HRESULT

Release the ipersistfile ppf pointer

Coinvoke PPF, IPERSISTFILE, RELEASE

Mov HRESULT, EAX

.Endif

Release The IshellLink PSL POINTER

Coinvoke PSL, ISHELLLINK, RELEASE

Mov HRESULT, EAX

.Endif

Free Our HEAP SPACE

Invoke Heapfree, Hheap, Null, Pwsz

Mov Eax, HRESULT; Since We Reuse this Variable over and over,

IT Contains The Last Operations Result

RET

CocreateLink Endp

; ------------------------------------------------- --------------------

End Start

Rsrc.rc

// Resource.h May Be Found in ICZelion's Tut # 10-1

// it is well mainy moving to your / masm32 / incrude / folder

#include "/masm32/include/Resource.h"

#define IDC_ICON1 1001

#define IDC_ICON2 1002

IDI_ICON1 Icon Moveable Pure Loadoncall Discardable "Plane.ico"

IDI_ICON2 ICON MOVEABLE PURE LOADONCALL DISCARDABLE "Trffc14.ico"

转载请注明原文地址:https://www.9cbs.com/read-26603.html

New Post(0)