Disable InfoCenter in AutoCAD 2010

[Update: See Disable AutoCAD InfoCenter]

In case you missed it, Tony Tanzillo has posted instructions for disabling the InfoCenter in AutoCAD 2010. AutoCAD 2010 starts faster when the InfoCenter is disabled.

To make it easy, I’ve created an AutoLISP file that defines commands named DisableInfoCenter and EnableInfoCenter:
DisableInfoCenter.LSP

Alternatively, you can just paste the following lisp at the AutoCAD command line to disable it and be done with it. Note that you need to restart AutoCAD for the change to take effect.

(vl-load-com)
(vl-registry-write (strcat "HKEY_CURRENT_USER\" (vlax-product-key) "\InfoCenter") "InfoCenterOn" 0)

ObjectARX 2010: Dealing With Missing Exports

In the new ObjectARX 2010 SDK, Autodesk has added some new virtual member functions that are not exported as they should be. For example, the AcGiFaceData class has had two new virtual functions added for setting and getting the face transparency:

class AcGiFaceData: public AcRxObject
{

//[… deleted for brevity]
ACDB_PORT virtual AcDbObjectId* materials() const;
ACDB_PORT virtual AcGiMapper* mappers() const
virtual void setTransparency(const AcCmTransparency *transparency);
virtual
AcCmTransparency* transparency() const

private
:
AcGiImpFaceData *mpAcGiImpFaceData;
};

As you can see, whoever added the new functions neglected to prefix them with the ACDB_PORT macro. ACDB_PORT evaluates to __declspec(export), which tells the compiler to export the function. Since the macro is missing, the new functions are not exported from acdb18.dll.

Since these are virtual functions, you won’t have any problems calling them through a pointer to an AcGiFaceData object that was constructed by AutoCAD. The problem arises when you derive a class from AcGiFaceData. Since the functions are not exported, the linker has no way of resolving their address for creating the virtual function table of your derived class. This results in linker errors:

acrxEntryPoint.obj : error LNK2001: unresolved external symbol “public: virtual void __thiscall AcGiFaceData::setTransparency(class AcCmTransparency const *)” (?setTransparency@AcGiFaceData@@UAEXPBVAcCmTransparency@@@Z)
acrxEntryPoint.obj : error LNK2001: unresolved external symbol “public: virtual class AcCmTransparency * __thiscall AcGiFaceData::transparency(void)const ” (?transparency@AcGiFaceData@@UBEPAVAcCmTransparency@@XZ)

Following is an example that results in these errors:

class AcGiFaceDataEx: public AcGiFaceData
{

public
:
AcGiFaceDataEx() {}
~
AcGiFaceDataEx() {}
}
Test;

The only solution is to provide an implementation of the missing functions. In this case, it could be accomplished by something like this:

class AcGiFaceDataEx: public AcGiFaceData
{

AcCmTransparency* mpTransparency;
public
:
AcGiFaceDataEx() : mpTransparency( NULL ) {}
~
AcGiFaceDataEx() { delete mpTransparency; }
virtual
void setTransparency(const AcCmTransparency *transparency)
{

delete
mpTransparency;
mpTransparency = (transparency? new AcCmTransparency( *transparency ) : NULL);
}

virtual
AcCmTransparency* transparency() const { return mpTransparency; }
}
Test;

This will fix the linker errors, but there is no guarantee that it will work as intended. AutoCAD might access its internal transparency value directly without calling through the member functions, which means it would never “see” the transparency set through the replacement member functions. Furthermore, the addition of the new pointer member changes the size of the class, which causes AcGiFaceDataEx arrays to have a different memory footprint than AcGiFaceData arrays. Lastly, what if Autodesk fixes the problem in a future AutoCAD service pack?

The ideal solution should not change the size of the class. It should check at runtime whether the function is exported, then use the exported function if it exists. That way, code that is written now will use the exported function if and when it becomes available in a future version of AutoCAD. When the function is not exported, an alternate implementation must be provided. This is not an unusual scenario, and the solution I present for the specific case of AcGiFaceData can be adapted to the more general problem.

In the AcGiFaceData case, the missing functions are virtual functions. Knowing this, it is possible to use a trick to get the address of the real function. In the code below, the function getAcGiFaceData_vtable() constructs a temporary AcGiFaceData object, from which it extracts a pointer to the object’s virtual function table. The virtual function table is just an array of function pointers, so the address of the desired function can be obtained by indexing into the virtual function table. The question is, how far? By counting virtual functions and data members starting from the top of the class hierarchy: in this case, 6 virtual functions in AcRxObject plus 16 virtual functions in AcGiFaceData = 22.

Note that obtaining a function pointer this way relies on Visual C++ implementation details, but this is safe to do since all ObjectARX modules must be compiled in Visual C++.

Following is my solution to the missing AcGiFaceData functions:

#pragma warning(push)
#pragma warning(disable: 4608)
template < typename Src, typename Dest >
Dest force_cast( Src src )
{

union
_convertor { Dest d; Src s; _convertor() : d(0), s(0) {} } convertor;
convertor.s = src;
return
convertor.d;
}

#pragma warning(pop)

static
FARPROC* getAcGiFaceData_vtable()
{

static
FARPROC* rfVTable = *(FARPROC**)&AcGiFaceData();
return
(rfVTable? rfVTable : NULL);
}

void AcGiFaceData::setTransparency( const AcCmTransparency* transparency )
{

typedef
void (AcGiFaceData::*F_setTransparency)( const AcCmTransparency* );
static
F_setTransparency pfSetTransparency = force_cast< FARPROC, F_setTransparency >(GetProcAddress( GetModuleHandleA( “acdb18.dll”), “?setTransparency@AcGiFaceData@@UEAAXPEBVAcCmTransparency@@@Z” ));
if
( !pfSetTransparency )
{

static
FARPROC* rfVTable = getAcGiFaceData_vtable();
if
( rfVTable )
pfSetTransparency = force_cast< FARPROC, F_setTransparency >( rfVTable[22] );
}

if
( pfSetTransparency )
(
this->*pfSetTransparency)( transparency );
}

AcCmTransparency* AcGiFaceData::transparency() const
{

typedef
AcCmTransparency* (AcGiFaceData::*F_transparency)() const;
static
F_transparency pfTransparency = force_cast< FARPROC, F_transparency >(GetProcAddress( GetModuleHandleA( “acdb18.dll”), “?transparency@AcGiFaceData@@UEBAPEAVAcCmTransparency@@XZ” ));
if
( !pfTransparency )
{

static
FARPROC* rfVTable = getAcGiFaceData_vtable();
if
( rfVTable )
pfTransparency = force_cast< FARPROC, F_transparency >( rfVTable[23] );
}

if
( pfTransparency )
return
(this->*pfTransparency)();
return
NULL;
}

What’s New in the AutoCAD 2010 EULA

Everyone else is discussing all the cool new features in AutoCAD 2010, so I decided to have a look at what’s new in the EULA (End User License Agreement). I compared the AutoCAD 2010 EULA for US/Canada to the AutoCAD 2009 EULA. I won’t divulge the process I used to automate the comparison, because the odds are pretty good that I violated the EULA somewhere along the way, and I want plausible deniability.

The first change I noticed is that the AutoCAD 2010 EULA contains more shouting. The 2009 EULA started out in a fairly mellow mixed case with a few shouts thrown in for effect, but the 2010 EULA dispenses with the lower case and launches right into a multi-paragraph avalanche of screaming block letters. Apparently nobody was listening, so they turned up the volume.

Substantively, there are a number of very interesting changes. The following was added to the preamble:

SOFTWARE OBTAINED FROM THIRD PARTIES THAT HAVE NOT BEEN AUTHORIZED OR ALLOWED BY AUTODESK, DIRECTLY OR INDIRECTLY, TO SUPPLY SOFTWARE IS LIKELY TO HAVE BEEN MADE AVAILABLE IN VIOLATION OF AUTODESK’S RIGHTS. IN SUCH AN EVENT, AUTODESK IS NOT OBLIGATED TO ISSUE AN ACTIVATION CODE OR OTHERWISE PERMIT YOU TO INSTALL OR USE THE SOFTWARE.

Next time you’re eyeing that used copy of AutoCAD 2010 on eBay, be warned that Autodesk is not obligated to permit you to install or use the software. They don’t come right out and say that they won’t allow it, so maybe they won’t mind — but then what’s the point of including this clause? Tim Vernor won’t be very happy about this change.

Moving along, I see that they added a definition for “Uninstall”, defining it as “to destroy or remove”. The definition of “User Documentation” was very slightly changed from “…after You acquire or Install the Software…” to “…when or after You acquire or Install the Software…”. Incidentally, did you know that Autodesk considers an AutoCAD reseller’s invoice to be “user documentation”?

Rounding out changes in definitions is a change in the definition of “You”. Yes, Autodesk has redefined “You” whether “you” like it or not.

I could go on and on about small wording changes, and while it would be interesting to contemplate why each change was made (and how many scheming lawyers it took to do it), we’d risk missing the forest for the trees.

Section 2.1, “License Grant”, contains ominous new language. The following has been added:

You may Access the application programming interfaces that may be included with or in the Software or otherwise available from Autodesk for use with the Software (“API’s”) to develop programs, modules, components or functionality that (i) are compatible with and are used and/or interfaced with the Software and (ii) contribute significant value-added functionality or enhancements to the Software (“API Modules”) provided You may Install and Access such API Modules solely on Computers where a licensed copy of the Software is also installed and further provided such Installation and Access is solely in connection with Your Installation and Access of the Software and solely for Your internal business needs. You may not redistribute all or any portion of an API Module.

Read that again. That’s right, you may not write any “programs, modules, components, or functionality” unless they “contribute significant value-added functionality or enhancements” to AutoCAD. Furthermore, if you do manage to write a program that adds significant functionality, you may not redistribute all or any part of it. What are those guys smoking out there in California?

Finally at the end of section 2.1, they changed “No license is granted under the terms of this Agreement if You did not lawfully acquire the Software” to “No license is granted under the terms of this Agreement if You did not lawfully acquire the Software from Autodesk or from a third party who has been permitted or authorized by Autodesk either directly or indirectly to supply the Software”. Take that Tim Vernor!

In another nod to the Vernor case, section 2.3, “Upgrades”, adds a new requirement to “destroy all Autodesk Materials relating to the Previous Version or, upon request by Autodesk, return all such Autodesk Materials relating to the Previous Version to Autodesk or the company from which they were acquired”. This is important language that could persuade a court to view an AutoCAD purchase as a license instead of a sale, thereby giving Autodesk the power to control the secondary market.

Interestingly, section 2.4, “Crossgrades”, requires that the previous software be uninstalled within 60 days, but has no requirement that it be destroyed. However, new language in section 2.7, “Termination”, which requires the software to be destroyed “upon termination of the license grant or this Agreement”, apparently covers both cases.

A funny change in section 3.2.3, “Transfers”, appears to close a loophole. The AutoCAD 2009 EULA disallowed transfers to “any other person”; the AutoCAD 2010 EULA disallows transfers to “any other person or legal entity”. Considering a license transfer? Make sure it’s to an illegal entity!

Section 4, “ALL RIGHTS RESERVED”, was rewritten. The rewrite introduced a grammatical error (“and You have not other rights”), but otherwise I don’t see that much changed. It still ends with the now familiar directive that “The Software and User Documentation are licensed, not sold.”

Finally, the infamous “audit clause” has been revised. Not the way you may have hoped, I’m sad to report. Luckily the change was a minor one that doesn’t make the clause any more overbearing than it already was.

Isn’t change wonderful?

Software Licensing: A Case For Reform

I want to consider software licensing practices in general, but with the specific facts and history in the Vernor vs. Autodesk lawsuit as a backdrop.

In the Vernor case, Tim Vernor purchased several boxes of AutoCAD software, and never even read, let alone agreed to, the terms of the license agreement inside the box. When Vernor listed the AutoCAD software for sale on Ebay, Autodesk sent Ebay a notice that claimed Vernor’s auction violated Autodesk’s copyright. In order to benefit from the safe harbor provisions of the Digital Millennium Copyright Act (DMCA), Ebay was obligated to remove the auctions. Vernor responded by filing a lawsuit accusing Autodesk of making false copyright violation claims.

Additional facts have since come to light. For one, we’ve learned that the AutoCAD software that Vernor purchased had been previously upgraded to a newer version. Vernor did not know this when he purchased the software; and in any case, it’s not clear that this fact has any bearing on the outcome of the suit.

Given this set of facts, let’s analyze the Vernor case not from a purely legal perspective, but from a more abstract “moral” perspective. After all, society is the ultimate arbitrator of what is wrong and what is right with respect to our laws. We ultimately determine whether laws are fair by whether we follow them willingly (and whether we put pressure on our legislatures to change them).

Steve Johnson opines that Autodesk is morally right in the Vernor case, because the software Vernor purchased was “tainted” due to having been upgraded by the original owner. In Steve’s view… [see Steve’s comment below where he chides me for ascribing this view to him – O.W.] Presumably, one who holds this view sees Vernor’s original purchase as akin to someone purchasing stolen goods. With stolen goods, the law (and hopefully our moral compass) recognizes that the purchaser of the stolen goods has no legal right to them.

Autodesk offered the original owner a discounted price for a newer version of AutoCAD in exchange for a promise to destroy the older version. The original owner reneged on its promise to destroy the old version, and sold it to an unwitting buyer instead.

It follows that both Autodesk and Tim Vernor were treated unfairly by the company that sold the AutoCAD software to Vernor. Despite the company’s history of using pirated software, Autodesk gave them the benefit of the doubt when selling them a discounted upgrade. Vernor, by all accounts, had no idea and no way of knowing that the software he purchased had been previously upgraded. This is a recipe for disaster.

Unfortunately, this sort of disaster is all too common. In many cases, software users simply don’t read license agreements. If they do read license agreements, they don’t understand them. After all, most of us are not lawyers, and we can’t reasonably be expected to hire a lawyer to evaluate the license agreements of every software product we use. How then can we be expected to follow them exactly and without fail?

Consider that it’s entirely possible that the company from which Vernor bought his AutoCAD software had no idea that they had agreed to destroy the upgraded AutoCAD software. At least from a moral perspective, we can have some sympathy for the company if they honestly had no idea they were violating any agreements when they sold the software to Vernor.

Could Autodesk have required the upgraded AutoCAD software to be returned, or required certification by an independent “software recycler” that it had been destroyed? Sure they could have. In fact, such requirements did exist in the early days of software license agreements. Had Autodesk done so, the Vernor court would probably have concluded that AutoCAD was licensed, not sold.

Why even require the old version to be destroyed when upgrading? If we stop using the old version, why shouldn’t we be allowed to sell it at market value? Doesn’t recycling old software make just as much sense as recycling old tires? We have been conditioned to believe that discounted upgrades are good for us, but are they really?

Would we accept a legal regime under which tire manufacturers could force us to destroy our old tires as part of the new tire purchase agreement? Oh, you say, that comparison isn’t valid because tires eventually wear out of their own accord, whereas old software continues working forever! First of all, old software doesn’t continue working forever. How many people still use VisiCalc? Furthermore, what would this line of reasoning conclude about potential tires of the future that last forever? We’d have to start licensing tires instead of purchasing them!

What would happen if software vendors could not legally prevent “used” software from being resold on the open market, no matter how it was purchased or upgraded? For one, it would increase competition, because new versions of software would be competing not only against software from other vendors, but also against older versions of itself. In a world where software is priced based on what the market will bear, the net effect would be lower prices and higher quality (not to mention less frequent “upgrades”) for all software.

I think the Vernor case is just one example illustrating how the current software licensing system has sprung a leak, and is in need of repair. Can it be patched, or does it need to be replaced? Can the bleeding be stopped at the ankle, or should it be stopped it at the neck? This is a classical case of the Petcock Problem.

Software industry advocates like the Business Software Alliance (BSA) proclaim that the solution is educating consumers. Education may be important, but I think that “educating consumers” should not be left to an industry alliance.

I have some ideas about how the system can be reformed, but I think we have to start by recognizing that there’s a problem.

Software Licensing: Who’s On First?

I’m a firm supporter of intellectual property rights. I fully support the rights of software publishers to own and profit from their creative work. I make my living as both a consumer of software and a publisher of software, so my views on software licensing reflect what I consider to be a healthy symbiosis between producers and consumers.

Intellectual property laws are (or should be) designed to protect this symbiotic relationship for the public good. The patent system is designed not to protect patent owners from pirates, but to promote inventions and improvements on previous inventions that benefit the public. The fact that patent laws do help to protect patent owners from pirates is merely a side effect of the underlying goal of promoting the public interest. We, the public, grant exclusive rights to patent owners for a specific time in exchange for them making public the details of their invention. Innovative inventors can thus build on a body of previously published inventions rather than starting from scratch. This system of “open source” innovation speeds the evolution of technology, and everybody benefits from it.

Copyright laws must be viewed in the same light. Copyright laws are designed to promote and enhance the public good by encouraging the production and publication of creative works. In exchange for giving copyright owners certain rights for a certain period of time, the public gets to enjoy and build upon a body of creative work. Some argue that the benefit of copyright protection provides a financial incentive to create the works in the first place, and that without such an incentive the works would never be produced at all. While this is undoubtedly true, consider that there are other ways to provide financial incentives (by providing government grants, for example), so I think it’s important to view this aspect of copyright protection as a consequence of the goal to promote the public interest, not as a goal in and of itself.

Copyright laws have long recognized a need to prevent copyrights from being abused by providing exceptions to the protection they afford to publishers. The Fair Use doctrine is the most common such exception in US copyright law. The First Sale doctrine (or “exhaustion rule” in some jurisdictions) is another example of a limitation on copyrights. These exceptions and limitations evolved in response to attempts by copyright owners to abuse copyrights in a way that contravened their purpose of promoting the public interest.

Software licenses are a relatively new phenomenon, but they rely on very old law: contract law. It is important to understand that a software license agreement is a contract. The commercial software publisher agrees to give us limited and conditional copy rights and authorizes us to use the software in exchange for a fee. If the license agreement that we agreed to authorizes us to install and use the software on one computer, but we install it on ten computers, then we are violating both contract and copyright law (because we copied the software without permission). If the license agreement that we agreed to forbids us to resell the software to someone else, but we decide not to use the software ourselves and sell it anyway, we are violating only contract law (because we made no unauthorized copies).

There are several contract law issues typically encountered with software license agreements.

First, typical commercial software license agreements suffer from their unilateral nature. The contract is drawn up by the publisher with no negotiation or input from the consumer. Some question whether these are valid contracts in the first place, because they lack the “meeting of the minds” element that some judicial interpretations of contract law require.

Second, software license agreements are not usually consummated until after the sale, when the software is finally installed. We purchase the software, essentially committing to our side of the bargain before we even know the terms of the contract to which we must eventually agree in order to use the software. This is inherently unfair, and there are still many unsettled questions about whether or not such a contract can ever be equitable and enforceable.

If you’ve been following the Vernor vs. Autodesk lawsuit, you’ll know that the US federal district court in that case ruled that AutoCAD software was sold, not licensed, and therefore subject to the First Sale Doctrine. The First Sale Doctrine says, in essence, that a publisher cannot contractually restrict the downstream resale or distribution of a copyrighted work beyond the “first sale”. The court, at least in its initial ruling, rejected Autodesk’s argument that AutoCAD was licensed, and therefore exempt from the First Sale doctrine. It should be noted that the Vernor lawsuit is far from over, and this first sale decision could well change before the dust settles.

The courts will eventually reach a final decision in the specific case of Vernor vs. Autodesk, but why was this lawsuit even necessary in the first place? It’s difficult to envision any outcome in which every injury is rectified. It could even be argued that everybody loses, no matter the outcome. And this is just one case in one jurisdiction.

In the end, the final result of the Vernor case may not have much impact on how software is sold. It ultimately comes down to us, the union of consumers, to decide what kind of system we want. Unfortunately, right now we’re doing the software limbo while we wait faithfully for the next service pack. I think that we need more than a service pack. A system restore might be in order.