Friday, April 6, 2012

AutoCAD 2013 and LiteHtml.dll

Installing AutoCAD 2013 is complaining about LiteHtml.dll. Whats the story?

I can't say for sure, but I think you'll find that you have an over zealous system administrator who decided to deploy a security system that can only have been designed by chimps, then implemented by the most idiotic intern at Microsoft.

Go read this Knowledge Base article: http://support.microsoft.com/kb/2264107

Can you believe that? Some idiot thinks that DLLs are always completely self-contained, that no-one other than Microsoft might build an application where DLL1 depends on DLL2 which happens to be delivered as part of the same product.

This wouldn't be so bad if the numb nuts that actually implemented the security feature actually knew what they were doing. It appears that setting the CWDIllegalInDllSearch entry does not "omit the current directory from the search". Instead, it changes the order it considers directories. If a matching DLL is in the current directory, it halts the scan immediately. Doesn't check that the DLL would have been found via the official path strategy - it just stops.

Now, it's fine to say "but this is a vector for malware". Sure it is, but if someone can install a DLL into your application directory, then they can change your application as well, so this hack prevents *nothing*.

In case one of the afore-mentioned chimps is listening, they should find someone smarter than they are and ask what the letters in DLL mean. Dynamic Link Library. Suggesting that you can work around the problems this security setting causes by explicitly (and manually) loading the libraries you need with LoadLibrary() misses the point that there are no published APIs that tell you what libraries a specific DLL needs. If I have to write my app so that it analyses every DLL it loads, then every DLL that *they* load, recursing till I hit metal, then there is no point in actually *linking* against those libraries.

Thursday, May 19, 2011

Grandma's Apple Pie (as dictated by Mum)

Short Crust Pastry


Blend 125g butter, 125g plain flour and 125g self raising flour in a kitchen whiz.

Add 2 tablespoons of caster sugar and blend.

Add 1 egg yolk and combine.

Add 2-3 tablespoons of ice water (until the pastry almost combines)

Press pastry into a ball, then separate into 2/3 and 1/3 disks flattened out.

Wrap in plastic and chill for 60 minutes.


Apple Filling


Peel, core and slice 5-6 large Granny Smith Apples. Add 1 lemon, cut into quarters. Add 1/4 cup water (up to 1/2 cup).

Bring to boil and cook till softened. Add 1/2 cup sugar and stir until dissolved. Leave till cold.

Put pastry in tin and add cold apple, being sure to remove lemon. Cover with pastry. Brush the top with egg white, then sprinkle with caster sugar.


Cook at 220C for 10-15 minutes.

Turn oven down to 180C and cook for 25-20 minutes (ie, make the total oven time about 35 minutes).

Sunday, February 27, 2011

Samba NAS and error code -36

I just bought a Seagate GoFlex Home NAS and was wanting to backup a bunch of files to it. I ran their installer, installed all their recommended tools, configured the server, and got a Folder on my desktop representing the "GoFlex Home Public" folder on the server.

The first thing I tried to backup was their installation software, and I got this:

The Finder can’t complete the operation because some data in “some folder” can’t be read or written.
(Error code -36)

It's taken me several hours and lots of unsuccessful internet trawling to finally work out what the workaround is, so I figure its worth a post here where Google can find it for the next guy.

The problem appears to be related to the use of extended attributes, which Snow Leopard loves to attach to files these days. I believe that there is some sort of problem writing files with the com.apple.quarantine attribute to Samba mounted disks. Whilst you can try to use xattr -d to remove those attributes from your files, its tedious and very error prone.

Similarly, I found that sometimes files got stuck on the drive - you couldn't remove them, if you tried (in the terminal) you'd get permission errors. Nothing, sudo included, would allow you to fix the permissions. Yet looking in a terminal window with /bin/ls, they looked fine.

Short answer: Don't use the GoFlex Home Agent to mount network folders.

This always uses the smb: protocol to access the server. Instead, use the "Connect to server..." command on the "Go" menu in the finder, and explicitly specify that you want to use the afp: protocol instead.

Once I switched to using afp:, all of the spurious errors went away. I was able to delete all the temporarily stuck files, and I could copy whatever I liked onto the drive, regardless of the extra attributes.

Strangely enough, when I then tried out the Memeo Backup that Seagate include in the package, it warned me that my backup volume is afp: and I should use smb: instead. Yeah right. However, it looks like one reason they recommend smb: is that the afp: volume didn't seem to auto-mount when I went back in - I had to mount it for them.

Update:

Alternately, you can just wait for Apple to release OSX 10.6.7 which "resolves an issue when transferring files to certain SMB servers". Clearly, this blog post blowing the whole issue wide open had them scared and they realised they had to fix it pronto, or face my scathing posts.

Update 2:

Hmmm, despite it "mostly" working, I keep getting errors from Time Machine saying it was unable to complete the backup - it looks to me like it fails if it has to mount the drive itself.

Moral: do not buy this drive if you want to use it for Time Machine backups.

Saturday, November 27, 2010

Why are my zeroes behaving like ones?

Guess the output of this program:

C:\>type x.c
#include <stdio.h>
#define ZERO 0
#define P(x) printf("x=%d",x)
main()
{
  P(ZERO);
}

C:\>.\x.exe
x=1

Duh, what?

Ok, I cheated, I didn't show you the stupid compiler option I managed to pass through the use of a slightly buggy makefile.


C:\>cl /D0 x.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.

x.c
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.

/out:x.exe
x.obj

For those who don't memorise command-lines, that /D0 essentially is instructing the compiler to "define a value for the symbol 0" and the default value for definitions is "1".

Yes, the Microsoft VC90 compiler actually allows you to redefine the value of INTEGER tokens in your source code. Same thing happens at VC100.

C:\>cl /D0 x.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.

x.c
Microsoft (R) Incremental Linker Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.

/out:x.exe
x.obj

C:\>.\x.exe
x=1

It could be argued that it only shows up if you have one preprocessor macro using the value of another preprocessor macro, and you have to use an unlikely command-line option, so its not that tragic. But seriously guys, Apple catches you doing that sort of stupid thing at command-line parsing time...

jeff$ cc -D0 x.c
<command-line>: error: macro names must be identifiers

... and those of that that grew up with ANSI-C use macros like this all the time.

#define NAME(l) l[0]
#define ADDR(l) l[1]
#define TYPE(l) l[2]

Having those 0, 1 and 2 become subject to the whim of the command-line is unthinkable.

This all came about because of a Python-generated command line. I thought I was creating

CL /DOPTION0 x.c

but a bug meant I created this instead:

CL /DO /DP /DT /DI /DO /DN /D0 x.c

So I'm a lot more careful now.

Someone did point out to me that "All computer programs are just 0s and 1s. Looks like this one was just 1s".

Computer geek humor.

Thursday, July 2, 2009

.NET corrupts heap when marshalling LPSTR

(Hi Lizzie)

I've just spent the best part of a week trying to track down why my bridge from C# to C++ was working on Windows XP but crashing sporadically on Windows 7, and the answer is that .NET marshalling is trickier than you think for strings.

Essentially, I had this:

[DllImport("mydll.dll",CharSet=Ansi,CallingConvention=Cdecl)]
[MarshalAs(UnmanagedType.LPStr)]
private static extern String LookupCorrespondingString(Int32 key);


and in the DLL, I had

__declspec(dllexport) const char *LookupCorrespondingString(int key);

Whenever I called this, it would get all the way into my DLL, I could tell it was going to return a value, but during the return operation, it would crash. When I ran it in the debugger, I got output messages about how memory was being free'd into the wrong heap.

Eventually I found this article:
https://blogs.msdn.com/dsvc/archive/2009/06/22/troubleshooting-pinvoke-related-issues.aspx
which contained the useful quote (emphasis mine):
When a string buffer allocated by native code is marshaled to managed code, CLR Interop marshaller will allocate a managed string object and copy the contents of native buffer to the managed string object. Now in order to prevent a potential memory leak, CLR Interop Marshaller will try to free allocated native memory. It does so by calling CoTaskMemFree. The decision to call CoTaskMemFree is by-design. This can at times lead to crash, if memory was allocated by the called-native function using any API other than CoTaskMemAlloc family of API’s as custom allocators may allocate on different heaps.
And there was the answer. .NET was freeing the block of memory I had passed to it to help me "prevent a potential leak". The problem being the lack of ability to communicate the 'const-ness' of the underlying DLL entry point's return value in the MarshalAs() attribute.

The solution was to declare the entry point differently:

[DllImport("mydll.dll",CharSet=Ansi,CallingConvention=Cdecl)]
private static extern IntPtr LookupCorrespondingString(Int32 key);


and then when I call it, do the marshalling explicitly.

String s = Marshal.PtrToStringAnsi( LookupCorrespondingString(k) );

After I bitched and moaned about how this stuff isn't documented anywhere, Manish Jawa kindly pointed out that it is, in fact, documented in the very first sentence on this page: http://msdn.microsoft.com/en-us/library/f1cf4kkz.aspx - you can't ask for more than that.

Actually, you can and they give it to you here: http://msdn.microsoft.com/en-us/library/x3txb6xc.aspx - the problem I was experiencing and its solution spelled out.

So, the moral of the story is: if you pass native strings to .NET via the marshalling interface, make sure you use IntPtr and PtrToStringAnsi() unless you want them to be free'd for you.

Wednesday, May 13, 2009

Embedding .NET in an otherwise native application

For reasons best known to the company I work for we embed the .NET CLR inside our otherwise native C++ MFC-based application, and for the last two weeks I've been trying to nail down why pretty much everything seems to work, except the windows where we embed the WebBrowser control via COM.  No matter what I tried, IOleObject::SetClientSite() would fail and the web browser would display as an empty white rectangle on the desktop instead of in our window.

This guy seemed to have a very similiar symptom, but no answer; however, it was a fair guess he had the same problem and it was something to do with threading.

One of the guys at AutoDESK Developer Support (thanks again) pointed out that the CLR initialises the main thread to use MTA (multi-thread-apartment) mode, whereas the WebBrowser control really only works with STA (single-thread-apartment) mode.  So, the solution was to ensure that I called CoInitialize(NULL) in our main thread before the CLR had a chance to mess things up.

Tuesday, March 31, 2009

".PDB files cannot be linked due to incompatible versions"

The message ".PDB files cannot be linked due to incompatible versions" can be displayed during builds, even if the .PDB file has just been created by the current compilation (ie, its just not possible that it was built by a different version of the compiler)

The problem is that the
mspdbsrv.exe process (which Microsoft uses to create PDB files) does not always terminate after linking.  If you have a mixed environment where you compile and link some modules with VC7.0 and then some with VC8.0, sometimes the 8.0 mspdbsrv.exe process hangs around and interferes with subsequent 7.0 compiles.

Solution: use the Task Manager to terminate it.