COM and ATL Law Blind Series

xiaoxiao2021-03-06  41

COM and ATL literacy (second book)

Second book, the story of the SALUTE interface

I'm going back to book, we have started an ATL project and briefly introduced you to the generated DLL output function.

And how global variables are going. This time, we will continue to return to the call and try to build a simple method.

But more should be theoretical.

In this lecture, we will come into contact with BSTR, Variant, we will see how to add ATL objects, how to go to one

Adding methods in the interface, and what you need to pay attention to during the process of adding methods, IDL and how to use VB to build us

s component.

Then open the last item we have not completed "atlhello"! OK! It is a better than using the MFC wizard now.

The generated "clean" frame. It is clean than you imagine! Well, look at my face? It is clean than my face! because

It does not provide objects that make external applications created. Maybe you will ask: "How do you know?" Ha! Flashlight

follow me! ...fast! Double-click on the _moudle on the left and then look at the right (this sentence you won't understand it?) Pay attention to the following

Row:

Begin_Object_map (ObjectMap)

END_OBJECT_MAP ()

For the ATL server, you should use the Object_Entry () macro in these two rows to designate exposure to external applications.

Object. Nothing here, so I said that it is clean than the face. "

Let's add a COM object! Choose Insert-> New ATL Object menu item, ATL Object Wizard

Just start. Take a look at the category on the left, list the objects it supports in each class. Notice the left Data Access

! Use Provider and Consume to add objects that support OLE DB templates! how about it? Is it attractive?

Step by step, let's build a simplest COM object, select the Objects on the left and select SIMPLE on the right.

Object, press Next, then output an object's name in the short name of the pop-up window, establish a simple

For example, enter: "Salute"! Ah! It's filled with it! Then we will not move. you also

You can take a look at the Attributes tab, but let's take a default value, press the OK button!

After a hard disk, there will be a CSALUTE class and a CSALUTE class in ClassView.

mouth. Huh? What interface is it provided to the outside world? That takes a look! Click on _Module on the left Globals again

What changes did you find on the right side of the macro mentioned on the right? right! Now our program can really work well!

Let it do, do you live? right! When you ask it, it can simply answer your sentence, simple? that

Just do it! Right click on Isalute and select Add Method on the shortcut menu, so I will pop up.

A dialog box. Enter "Hellomynameis" as the name of the method in "Method Name", in "Parame"

"[in] bstr sname, [out] bstr * Sanswers" as parameter information (maybe you

I can't touch my mind, don't worry, I will say later), in the end, let's look back at "Return Type" above, it is a fixed HRESULT type. Press the "OK" button! The Csalute-> Isalute of the left Class View tree is more

They just added the definition of the method, double-click it, see what code has been generated by the ATL wizard!

what! see it? When calling this method, we have to tell Sname who we are, and the method will answer

Sanswers returned to you. The wizard only adds a line of "return s_ok" in this function, then we will put your own generation.

Code adds! The code of the method after the addition is as follows. This code is not complicated, just need you know BSTR

Usage. Mom! This start is too much to talk about! You must first know that BSTR is using sysallocstring

And the associated function is allocated, you must use sysfreestring to release it. After reading the code below, we will talk about BSTR in detail.

STDMETHODIMP CSALUTE :: Hellomynameis (BSTR Sname, BSTR * Sanswers)

{

// Some string types such as W2a, OLE2T must be added before the string type conversion macro.

Uses_Conversion;

// Clear the contents of the output parameters

IF (* sanswers)

{

:: sysfreeestring (* sanswers); // Release a BSTR string

* Sanswers = NULL;

}

// Users call this function and don't tell me who he is!

IF (0 == SNAME)

{

* sanswers = :: sysallocstring (const olechar *) A2W ("talking! Is there something? Nothing

What is it? ! "));

Return S_OK;

}

Char lpszansianswers [256];

IF (Strstr (OLE2T (SNAME), "Clinton"))

Lstrcpy (lpszanswers, "roll!");

ELSE IF (STRSTR (OLE2T (SNAME), "Daming a row")))

LSTRCPY (LPSzansInswers, "Look at the people must be the talent of the country, where is it?");

Else

LSTRCPY (LPSZANSISWERS, "Although I don't know you, I am willing to make friends with you!");

// return value

* Sanswers = :: sysallocstring (a2w (lpszanswers));

Return S_OK;

}

how about it? Is it very clear? The only function you have not contacted is sysallocstring and

SysfreeString and A2W, OLE2T two macros. Wait until slowly. Want to add it in an automation server

Methods, attributes, events, etc., their parameters must meet some mandatory agreements, such as passing a character with the interface.

String data must be a BSTR type. The method usually assigned to the BSTR variable is to use Win32 API:

SysallocString, the method directly to the BSTR to the BSTR in the following method is wrong: "BSTR BSTR = L"

There's a wrong. ";". Maybe some strange, what is BSTR going? How did it use this?

How much is limited? In fact, it is a pointer to the WCHAR_T string, but it saves the number of characters of the entire string on the top of the string. There is a problem with it here, is it necessary to save the number of characters? A simple function can not find

Is the length of the string? what! To know, if I said that multiple '/ 0' characters are allowed in a BSTR string, then you still

Do you think this string is easy to judge? This is a different feature of BSTR, which can have multiple strings.

Terminator. In addition, in order to simplify the use of BSTR, ATL defines a class called CCOMBSTR in Atlbase.h,

You can take a look, you can learn a lot.

In addition, A2W, W2a is used to convert between Unicode and ANSI characters, you can find on MSDN

"A2W" sees more detailed information.

Below, let's take a look at "[in] bstr sname, [out] bstr * when adding this method above.

"What is going on. When we want to add a method, complete the name and parameter information of the method and press OK.

After the button, Wizard actually refers not only in the "Salute.h" and "Salute.cpp" files in C style definition letter.

In addition to the number, the interface method similar to the following line is also added to "Salute.IDL":

[ID (1), Helpstring ("Method Hellomynameis")] HRESULT HELLOMYNAMEIS ([In] BSTR

SNAME, [OUT] BSTR * SANSWERS;

A total of three places modified the source program.

You must find it, this is not a method of defining a function in C . Yeah, this sentence is actually used is a kind of called

The syntax of the Interface Definition Language (IDL), but it is virtually very similar to the syntax of C . What is the IDL?

In fact, write a COM program, there are still many work needs to do, in order to simplify the trivial taste of Dali,

Put the programs' attention to the functionality of the component, and the ATL introduces IDL to describe the interface. Use it to mention

For sufficient information, it is convenient for the parameters of the function to be adjusted between the customer and the server (if you use IDL, then you finish

Fully don't care about it. Next, you double-click the "Isalute" on the left to see the Atlhello in the code window.

The content of the IDL file! We should thank this document, it has done countless work for us! ! !

In order to better do your work behind you, you need to specify the parameter type for each function is input, output

Still entering output and other instructions, this is more old, it is recommended that you still look at the relevant books.

For IDL interface definitions, there are a few most important things, you must take a look:

1. When the interface function is defined, the requirements must be a pointer for output parameters! ! ! Reiterates the time: must be one

Pointer! ! ! Please look back at the way we just join, its Sanswers must be a pointer! ! Otherwise compile

Will go wrong.

2. The standard agreement of the string in COM is to use Unicode. That is, Wchar_T string, in COM, this data class

Types have become OLECHAR and LPOLECHAR by define. So in the program, the conversion function may often be used, and the conversion is used.

In the function of the function, you must first execute the USES_CONVERSION macro.

3. For optional parameters (there may be no parameters), the final and data types must be Variant in the parameter table, and the data type must be Variant! Note again: The output parameter must be a pointer!

Wow! What is Variant? You must have seen the definition of Variant, it is actually a variety of data

Great Union of the type, you can flexibly process the output and input parameters through this data type. In use

Be sure to use :: variantinit () function is initially value, there are a lot of Variant

The API function is used to operate Variant data, you can find a look at MSDN, take a look. Of course, M $ is to simplify the number

According to the type of use, CCOMVARIANT classes are also defined in Atlbase.h, you can refer to the source and MSDN

The interest is a deep understanding of it.

I have seen so many theories, are you already asleep? Get up, we have to try the automation services we have written.

The device!

Select the "build atlhello.dll" item in the "Build" menu, the hard disk is behind an extremely painful embarrassment.

Our automation server will be registered automatically, and you can use it immediately!

As far as I personally, the test components, the best tool is not "ActiveX Control Test Container" but

VB. Hurry up! Open VB with the fastest speed, we have to build a project to test our masterpiece with the fastest speed!

I dare to bet, you can also tie your right hand in two minutes!

Start VB. Select "Enginee -> Reference" and select "Atlhello 1.0 Type Library". Place it on the form

A Text and a Button control, then add the following code in the Click event of the Button control:

Private submmand1_click ()

Dim a as new salute

Dim Sanswer As String

A.hellomynameis text1.text, sanswer

Msgbox Sanswer

End Sub

OK! Now run the program, you can enter the text of "Clinton", "Daming a row" in the Text box.

what's happening!

If there is still a next lecture, we may have to build a bit of practical value.

I have to drink saliva, everyone, look back.

In addition, tomorrow is my 2-year-old birthday year, I am willing to share my happiness together! !

COM and ATL Law Blind Series (3)

Another start: Macrovirusmaker out of the world.

thank you all! This year's birthday is the happiest time! Thank you everyone!

what! See the topic of this article, don't you misunderstand -----? ! How to be a virus machine? ! Actually it is just from

The name of the person heard the name, let everyone be interested in this article, two can make this example "expandability"

Different, if I can stick to it, maybe this is really a complete? ? Production machine? ! I do not know. Since

Start here, we assume that you really want to write a Word macro virus production machine, which can be specified by the "external program"

Attack's Word file name, then ... then I haven't thought about it yet! Let's go step down step by step! Nothing! Anyway, now

The macro's spread mechanism has already known (mixed with a finger on the network) is charged by "beautiful kill" source code).

The first two times have known how to build an ATL project and how to add an ATL component how to add a method, etc.

. This time we will build a new one from the beginning, complicated than two times, but more interesting automation than the last two times.

. This time, the establishment and generation of OLE will be the focus of our discussion.

let's start! By the steps below to generate an ATL application, everyone will! Self arrive!

1. Create an ATL project, name is: "Macrovirusmaker", "Server Type" selected "DLL",

Other don't choose anything else.

2, "INSERT ATL Object" -> "Objects" -> "Simple Object". Names-> ShortName

= "Worker". Attributes-> iSupp PorterrorInfo selected (after selecting this item, we can in the program

Generate OLE anomalies). Other silence values.

3, use the right-click on the left IWORKER to add two Method: "Startwork" without parameters,

"Endwork". In fact, they don't have much purpose, just startwork, do some initialization work, and Endwork

Do some "finish" work. We do it, the program that uses this component must first adjust after establishing the component.

Use StartWork and must call the endwork last.

4. Use the right-click on the iWorker to select "Add Property ..." to add the WordFileName property.

Property Type = "BSTR" Property Name = "WordFileName" selected Get Function and Put Function.

Use the right-click CWORKER to select "Add MEMBER VARIABLE ...". Variable

TYPE Select "BSTR", Variable Name Enter "M_BstrWordFileName".

The WordFileName property is the name of the Word document we want to "Operation", and we add a member in CWORKER.

Variables save this value.

In this way, we have established a simple ATL application framework. After the top two discussions, everyone is not

Is it very familiar with the above operation? what! I am so happy! Then come, let's take a look at what new content today?

From the easiest way, let's add two interface functions for StartWork and Endwork. Cifferker on the left

-> Is there a startwork in iWorker? what! What do you do? Double click on it!对! Use this method to push. repair

The two functions after the change are as follows:

Stdmethodimp CWORKER :: Startwork ()

{

m_bstrWordFileName = null;

Return S_OK;

}

StdMethodimp CWORKER :: Endwork ()

{

IF (M_BStrWordFileName)

{// If necessary, release the string

:: sysfreestring (m_bstrwordfilename);

}

Return S_OK;

}

Do you think that their content is ignorant? Don't take it! The following functions are interesting:

Why is it interesting? Because you must have a problem: "I obviously defines WordFileName is an attribute, how

What is the source code of this property in the program, turn into two prefix functions? "I said the old brother, don't look at anything with" outside our line "! Unconsciously, you have already entered the inside of the automation server.

The part said that the value assignment to the attribute is not different, but for us, their difference is very big! Get_ * is external

The program is to obtain the attribute value; put_ * is an external program to assign a value to the attribute.

If you can't remember, tell you a loss. You simply remember that "output parameters must be a pointer"! This

Do not? The parameter of GET_WORDFILENAME is a pointer, which must be an external program to get attribute values! Contrary ...

Let's! However, you'd better not say so, if you define a complex property in the future, there is a pointer type in the parameter

If you don't judge it. This is just a "predecessor", I don't listen to you.

The code of GET_WORDFILENAME and PUT_WORDFILENAME is as follows. Note: The following code is not perfect, it only

It is to let you understand, behind, we will modify it to make it more perfect.

STDMETHODIMP CWORKER :: get_wordfilename (BSTR * PVAL)

{

IF (* pval)

{// If necessary, release the string first

:: sysfreeestring (* pval);

}

IF (M_BStrWordFileName)

{/ / Assign strings for the return value

* pval = :: sysallocstringlen (m_bstringfilename, :: Systringlen (m_bstrwordfilename);

}

Return S_OK;

}

StdMethodimp CWORKER :: Put_wordFileName (BSTR NewVal)

{

Uses_Conversion;

IF (NewVal)

{

IF (M_BStrWordFileName)

{// If necessary, release the string first

:: sysfreestring (m_bstrwordfilename);

}

// Assign new strings

M_BstrWordFileName = :: sysallocstringlen (newval, :: systringlen (newval);

// TODO: Check if the file exists, if there is no existence, generate an OLE exception

File * fp = :: fopen (W2A (NewVal), "R");

IF (null == fp)

{

// File can't open

Return S_FALSE;

}

Else

{

:: fclose (fp);

}

}

Return S_OK;

}

In fact, the above code is a typical method of replicating the BSTR string. In the above code, there are two new APIs:

Systringlen and sysallocstringlen. Their role is as the name, I will not explain.

Note "Return S_false;" in the PUT_WORDFILENAME function, when the file cannot be opened,

It returns a false value, if the return value is used in Method, it is not thick, but it is afraid to use it in Property.

Custom, because the return value of the attribute is S_FALSE for external programs. then what should we do? what!

Here we will use a technique that is very interested in technology ---- OLE is abnormal. Let's take a detail, this can be

Is our focus of this discussion!

When writing components with C , you know that we can use two exceptions, one is C exception, which can only be used in defining it; the other is OLE OL, it can pass the same type of error to Use the assembly

Ministry. For example, the VB of the ON Error Goto ... statement is actually used in "external program" in "internal"

The OLE exception defined in the order "(internal). When we add a Work interface, we have chosen" Support

ISUPPORTERRORINFO, enabling this server to find more information through IerrorInfo when an error occurs.

We only need to add a job using OLE.

The only preparation of our only need to generate an enumeration table of the error type and add it to the IDL file. note:

This enumeration table must also have its own CLSID (the problem is coming again! What is CLSID? We said later.), CLSID

You must generate with Guidgen.exe. Some comrades asked: "Hey! Why don't I have this program?" Don't worry, it is in VS6

Under the "/ Common / Tools" directory of the CD, copy it! Now we run Guidgen.exe, first

Select "Registry Format" and press "New Guid" and press the copy button, and the newly generated GUID is copied to the cut.

The version. Let's add the following code to MacrovirusMaker.IDL ... etc! That hand

What do you learn? How to open the IDL file? Hi! You don't have the iWorker on the left! Sit down!

Got! Don't wait later, I still talk about Guid, Uuid and IID here!

GUID is an abbreviation for the Globally Unique Identifier (globally unique identifier). GUID is a 128-bit

Structure. It is used to identify an interface that provides a special algorithm for generating the GUID (CocreateGuid generation)

GUD) to ensure that the GUID in the world is not repeated, to ensure convenient design

Component. And each interface has at least two identifiers, one is the class ID (CLSID) one is the interface ID.

(IID), they are actually a GUID structure. The relationship between these three is like this. Of course, GUID is also widely used

One identifies different components, or even used to make PrimaryKey values ​​in the database (eg Access).

In ATL, you often see the Refiid type, in fact it is "const IID &" define. Similarly,

I don't have to say more about the meaning of refclsid and refguid?

Please add the following code until the MacrovirusMaker.IDL file (in fact it can add this file)

Any place).

The first half of the following code defines a new error enumeration ID, and the lower half is not used, everyone is familiar.

But one thing to note: Custom OLE exceptions must not conflict with predefined types, the best way is

This is like this, avoiding far away, M $ always defines the error 50,000 (nor necessarily).

Typedef [

UUID (C1F8eda1-0ef1-11d3-94f4-99b4c6100d86),

Helpstring ("Worker Error Enumeration"]]]

ENUM TagworkRerror

{

Worker_ERROR_FILECANNOTOPEN = 5000

Workererror;

On top, we only define an OLE error type, of course you can add more error types to yourself!

OK! Then there is all the best, we can generate your own OLE! In order to simplify our work, ATL mention

For a AtlReportError function, we use a line of code to generate rich multi-collected OLE exceptions. how about it? for

ATL drinks! Take a look at MSDN, you can know that it has four parameters: the server's CLSID, error information string, interface

IID and error code. what! It seems that generating an error message is easy to be in charge! Inside (TMD, it is

Internal), AtlReportError retrieves and returns an error using IrrorInfo.

In this way, we can enter the "return s_false;" in the PUT_WORDFILENAME function.

The row is transformed! Demonstration code is as follows

// Note: This code is just replacing "Return S_false;" That sentence

// Return S_FALSE;

Return ATLREPORTERROR (CLSID_WORKER, "file can't open", IID_IWORKER, MAKE_SCODE

(Severity_ERROR, FACILITY_ITF, Worker_ERROR_FILECANNOTOPEN);

how about it? Generate an OLE exception in a sentence, do you feel special?

OK! Now we have completed the WordFileName property, and now you can use it.

Compilation! Compilation! Hurry and compile!

Then open VB. Create a project and save it. Because we have to use it often.

Choose "Project" -> "Quote" -> "Macrovirusmaker 1.0 Type Library"

Buy a text box on the form, create a button, then say this in the click Click event:

Private submmand1_click ()

DIM VIR AS New Worker

ON Error Goto Errproc

Vir.Startwork

vir.wordfilename = text1.text

Msgbox vir.wordfilename

Vir.Endwork

EXIT SUB

Errproc:

MsgBox "error:" & Err.Description

Vir.Endwork

End Sub

Then run, then enter an existing file name in the text box, such as "C: /Windows/Win.com",

It will return the string to you.

Then you try to rank a file name, it will say "there is an error: the file can't be opened", and the file is playing

Not open is the error message we defined in the interface! how about it? Is it a sense of accomplishment from your heart?

so sleepy! I'm going to sleep! Today, let's talk about it first!

See you next time!

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

New Post(0)