Category Archives: Windows

How Microsoft Won The API War on Windows only

Another release out of the door, and some time to put my thoughts in writing.

Did Microsoft lose the API war?

The title of this post is of course referring to the famous “HowMicrosoft Lost the API War” by Joel. I kept going back to that article when we were porting our product to Vista, as well as trying some of my personal projects on Vista. The more I think about it, The Raymond Chen Camp in Microsoft is still strong, and the API war is far from lost. And this article does not indent to pick on Joel, it just uses his article (which was very true in 2004) as a base to make a point.

  • Speculations in the article that Win32 will be replaced by WinFX or Avalon or whatever did not happen. Win32 is still there, still working fine. All the previous code I have tried worked seamlessly on Vista.
  • I still have not found a user application that worked on XP and does not work well on Vista (drivers and hardware – completely other story).
  • It took us about 2-3 weeks to get a product (involving a lot of complex kernel-mode drivers and system service) that worked on XP to work on Vista. As a comparison Panther to Tiger took six months. So Microsoft did really make it seamless to port even system software. User-mode software did not need any porting.

Who makes the best APIs?

Also, apart from not losing backward compatibility, Microsoft are still kings at making their APIs developer-friendly.

Example – you want you application to make an HTTP request and get the result. Both Apple and Microsoft have an API (Apple calls its CFNetwork, MS calls theirs WinINet) for that. Ok, so you write you application to use the OS-supplied API for the task. But you have customers behind corporate firewalls, using proxies. The user has set its proxy setting in the system, and their browser is working fine, but you application is not. What to do?

Well Microsoft will advise you to simply call InternetOpen with INTERNET_OPEN_TYPE_PRECONFIG, which will make your application inherit the browser settings (direct or proxy). What do Apple suggest…. this! Tenths of lines of code against a simple parameter of a function.

This happened in a multi-platform project I managed. The Windows developer just took a glimpse at MSDN, added the flag and the proxy issue was forgotten on Windows. The Apple developer took almost half a day to understand the article, copy-paste the example and adapt it to his code. A big productivity win for Microsoft.

Does it matter?

Still, sadly, Joel was right about the outcome. Developers no longer care to learn new APIs from Redmond, and .NET is not very popular either. It is not because of the API war though. The API war played its part but what really mattered is the market and the widespread use of virtualization technology.

No matter how small the combined market of Linux and OS X is, companies don’t want to neglect that. These days you see more and more application sites offering OS X or Linux versions of their software, and more and more hardware vendors provide Linux drivers for their hardware. It is not a single OS world anymore. And this affects developers’ choices of tools and languages. Joel was talking a lot about the backward compatibility and the old code. But how about new code? What will you choose today, if you are starting a brand new software? If possible of course you will choose a technology that does not limit you deployment abilities. If you ever have the choice of .NET over Java – you will choose Java, or regret it later when a customer says “We like you application a lot, but we are a Linux shop, does it run on Linux?”. In that moment, it is not very comforting to say to yourself “Ok, we lost that sale, but hey, Linux is only 2%, why should I care”. And if you choose a technology that binds you to an OS, which today has 99% of the market, you are still gambling, betting all your money on the chance the OS market does not change in the lifetime of your product. Of course, all this is valid for a certain range of applications. But for this range, the developers have started turning away from APIs and technologies that are bound to a specific OS (.NET, Objective C) , and preferring (where possible) cross-platform tools and languages like Java, Python, wxWidgets etc.

As a developer, I am a huge .NET fan. This is the combination of framework and development environment that IMHO makes a developer most effective. As a development manager though, I am a Java/Python fan. Even with somewhat less productivity with the later two, you are ready to deploy on any platform out there and this is becoming more important.

The role of virtualization

The other thing that hurt Microsoft bad is the virtualization technology boom. The biggest advantage of Windows is the huge amount of software available on it. A lot of people have been tempted to switch to Apple or Linux, but were being held back by that specific application that they can’t live without, which is available on Windows only. Well, with the Apple switching to Intel (enabling software like VMWare and Parallels on the Mac) and VMWare doing a Linux version it is not a problem anymore. I know a lot of people that switched and are now running that favorite application in a virtual machine.

Conclusion

So Microsoft won the API war. It did not matter. To win the developers back to Microsoft tools and technologies, they should make them available on all platforms. If there was .NET for Mac and Linux I would, as a development manager, push the developers to use .NET. With .NET being bound to Windows – it is a hard call to make since you are burning your bridges for a Mac or Linux version.

Share

Microsoft CRM Web Services

Lost almost half a day evaluating the best way to integrate our licensing with our corporate CRM. Why am I writing this? To hopefully save someone else’s half day.

After a glimpse at the SDK I figured out I wanted to use the CRM web services. They were simple, and had just the functionality I needed.

I wanted to try them quickly, so I:

  1. pointed my browser to http://localhost:5555/MSCRMServices/2006/crmservice.asmx
  2. clicked on Fetch
  3. Entered a valid Fetch XML and clicked invoke

500 Internal server error

The rest of the day was spent trying to figure that error. I decided there is a problem with the web interface, so I wrote a small C# function to try it:

CrmService s = new CrmService();
s.Credentials = new NetworkCredential(“administrator”, “admin”, “organization”);
// or s.Credentials = System.Net.CredentialCache.DefaultCredentials;
s.Url = “http://localhost:5555/mscrmservices/2006/crmservice.asmx”;
string a = s.Fetch(@”
<fetch mapping=’logical’>
<entity name=’account’><all-attributes/>
</entity>
</fetch> “);
MessageBox.Show(a);

Same Internal server error.

FireFox gave me some insights, which still didn’t help me figure out what’s wrong:
System.Runtime.InteropServices.COMException: Exception from HRESULT: 0x80041D1F.
at Microsoft.Crm.Platform.ComProxy.CRMQueryClass.ExecuteQuery(CUserAuth& Caller, String QueryXML)
at Microsoft.Crm.Sdk.SavedQueryServiceProvider.Execute(String fetchXMLString, ExecutionContext context)
at Microsoft.Crm.WebServices.CrmService.Fetch(String fetchXml)

At the end of the day, all the 500 Internal server errors and cryptic InteropService exceptions boiled down to permission problems. I was using the administrator account, which is not allowed to use CRM.

The problem here is not that CRM didn’t work correct. The problem is that both IIS and the COM exception were too cryptic. The 0x80041D1F is described on some sites, but it is a CRM specific HRESULT, not something that error lookup knows about.

I really hope this article saves your half a day so you can do something fun with it.

Share

Repair dynamic disks that go foreign

How to repair dynamic disks that go foreign or will not reactivate

Sometimes when frequently switching dynamic disks among machines, moving parts of the disks of a group amongst machines, or doing something not very simple sometimes the LDM (Logical Disk Manager) will break and some or all of the disks will go foreign or missing. The LDM is the table that contains information about all disks layout – partitions, stripes, etc.

In many cases you will be able to get to your volumes using “Import foreign disks” or “Reactivate disk“. Sadly sometimes the Windows Logical Disk Manager goes berserk and fails with “Disk group has no configuration copies” or some other cryptic error.

Consider you have done everything you thought of, and you don’t have a backup of your LDM created with Tiger Technology‘s Dynamic Disk Optimizer tool (which would have saved you). Then there is the last measure – re-building your dynamic disk configuration manually. The rest of this post will explain how do do it.

I assume you:

  • Remember by hard the layout – partition sizes, striping, spanning, etc. If you are not 100% certain do not proceed – you will DESTROY your data.
  • The you are at least a developer or sys admin. I will be talking in disk sectors, hex, cylinders and complex abbreviations like NTFS, NTLDR.
  • You are familiar with working with a disk Hex editor (like WinHex). If you don’t feel crafty with this – do not read further – ask for help
  • Understand this is just information I publish. Should you decide to rebuild your dynamic disks following this advise, and you lose your data as a result, the responsibility is yours.

Lets use a stripe of two disks as an example. It won’t import. It looks like this in disk management:

foreign.jpg

Step 1: First we have to backup the first 4096 bytes of your NTFS. Use a hex editor (like WinHex) to find the NTFS (it should be on disk 1). Depending on weather the disk is MBR, GPT, and how you partitioned the NTFS(es) might be in different places. Look for the string NTFS with the hex editor, and when you find it – check if it matches this picture:

backup.jpg

Then from the start of the NTFS sector, write 4096 bytes to a file somewhere. This is the important info to rebuild the volume. If you don’t successfully backup that, and continue – the data is LOST. Also remember disk number and offset where you took the backups from.

You have to do this step for each volume (not disk). You should end up with as many NTFS backup files as many volumes you had. If you had partitions in the middle of the disk – it might be tricky to find all NTFS headers.
Step 2: Convert the disks to basic
convert.jpg

Step 3: Convert back to dynamic

convertdyn.jpg

Step 4: Create your volumes again as they were. EXACTLY the same. When Windows ask to format the new volume DO NOT ALLOW.

format.jpg

Step 5: Write back all the NTFS headers you backed up in Step 1 (you remembered disk offsets and numbers as I told you right? If not – search for the NTLDR signature as screen on the WinHex screen shot above – it is on the next sector as you can see from the screen shot, and it will be there).

Step 6: Try to mount/access the volume. You should see your data :)

Share

Using OpenVPN on Windows Vista

Well, thanks to the long holidays I finally had time to give the Vista release a spin. For the purpose I used my company laptop – a Lifebook T4210 tablet PC. Since i was tempted to switch to Vista completely and wipe out the old XP, I had to prove that all the tools I need for my job will work. One of the most important was OpenVPN, since this is what we use to access our network.

The straightforward approach (simply installing and running it) did not work, since OpenVPN was failing to adjust my routing table. It uses an API (IPAPI) that does not work, even if I “Run as Administrator” it. Fortunately OpenVPN has an option to set routes by executing route.exe (route-method exe), which does the trick. Also, OpenVPN should be run as Administrator, which ruled out the option of using its own right-click menu “Start OpenVPN on this config file”. What i found works best is:

  1. Add to your .ovpn file the following two lines:
    route-method exe
    route-delay 2
  2. Create a one-line .BAT file to run openvpn on your .ovpn config file like this
    “C:\Program Files\OpenVPN\bin\openvpn.exe” [PATH_TO_OVPN_FILE]
  3. To start the VPN, right click on the bat file and choose “Run as Administrator

Enjoy.

Share

Get a hard disk serial number

I have been planning to write on that topic since October, but never got the time since I was pretty busy with the releases of MetaSAN and stoneGate. Now during the holidays I finally have time to post.

The issue that I came upon was (at the beginning) looking quite simple – get the serial number of a locally attached hard disk. My first approach was to simply use IOCTL_STORAGE_QUERY_PROPERTY and hope that Microsoft did all the work for me. Unfortunately this was behaving strange. On half the hard disks in our lab it would succeed and return the correct disk serial, on others it will fail (SerialNumberOffset being zero).

Ok, I think to myself, someone must have had the same problem – lets ask google. Soon I figured that 90% of my searches were ending into a commercially sold DLL named GetDiskSerial. Someone had solved the problem, and was selling the solution. By that time I had enough budget for a $19 toolkit, but could not accept that something I thought should be a simple API/IOCTL call should cost money at all. I downloaded an eval, it worked fine on all the machines I had at my disposal.

I did not give up, and after some more hours I found a utility called diskid32 and downloaded it. It did not work, but I found that the author published the source here. I extracted the part that was doing the IDENTIFY, compiled it and it worked fine for me. I did not figure out why their executable failed.

Anyway, here is a free alternative to the GetDiskSerial DLL – getdiskserial.zip.

The source has two functions with identical interfaces – GetDiskSerial1 and GetDiskSerial2. The first is using the MS IOCTL, the second – the method by Lynn McGuire (diskid32). You can easily make a super-function of the two, to always get the disk serial.

I am not claiming the source is my creation – I just wanted to share my experience and give you the result I came up with – simply combining the two approaches and making the interfaces/results match (the diskid32 returns the serial as text, while the MS IOCTL returns it as a string containing the hexadecimal values of the ASCII code of the disk serial).

I still think that the commercial DLL has some benefits – it has versions for various languages and development platforms and probably works with a wider variety of disks. I have not yet found a disk that neither IOCTL_STORAGE_QUERY_PROPERTY nor diskid32 will work on, but if you find one – drop me a line please.

Share

MSI setup requires .NET 1.1.4322

“Setup requires .net framework version 1.1.4322″ with version 2.0 installed

Lost almost half a day trying to install a MSI package that complained “setup requires .net framework version 1.1.4322″, and I had version 2.0 installed. I found the solution in the blog of Hannes Pavelka, which turned out to be one interesting development blog. You can see the solution of the problem here.

Share

Visual C++ Decorated Names Syntax

Ever wondered how Visual C++ encodes parameter info in the so-called decorated names?
This knowledge is close to useless, and the only time I needed it was when I tried to generate a DLL that needs to completely mimic another DLL’s exports. I wanted to re-create the original CPP & H file for a DLL that I had only the exports for. So I started looking on the Internet for info how decorated names are created. MSDN has just a little paragraph about decorated names stating:

A decorated name for a C++ function contains the following information:
The function name.
The class that the function is a member of, if it is a member function. This may include the class that encloses the function’s class, and so on.
The namespace the function belongs to (if it is part of a namespace).
The types of the function’s parameters.
The calling convention.
The return type of the function.

I found that info insufficient, so I decided to figure out the format by declaring functions and looking at the decorated name that the compiler generates. The conclusions I have made are for sure not complete, I just only went that far so that I can re-create the declaration of each of the functions in that DLL. But the result IMHO is usable and even if I have missed a type it can be easily added.

Here is what I have figured out about the format:

  1. C++ decorated names start with a ‘?’ sign.
  2. The name and namespace/class follows in format name@class@@
  3. Visibility specifier follows:
  4. A – private
    I – protected
    Q – public

  5. Unknown character follows (always A)
  6. Definition of the parameters (see below)
  7. The decorated name ends with “@Z”

Ok, so number 5 of the above list is pretty general :). Let’s be a little more specific :).
Types can start with an arbitrary number of the following modifiers:

PA: *
AA: &
PB: const *
QA: *const
AB: const &

The type signature follows. Here is the table:

E this pointer
P6 Function pointer (complete function declaration follows)
D char
X void
F short
J long
H int
M float
N double
O long double
E unsigned char
G unsigned short
I unsigned int
K unsigned long
_J __int64
_F __int16
_H __int32
_D __int8
? Type name follow terminated by @@
U User type. If it starts with a digit – index of user type. If it starts with a letter – new user type. Consider the following example – the function void func(MyType *a, MyType b) has decorated name of ?func@@YAXPAUMyType@@U1@@Z
V Similar to U. Not sure what it is about. Appears when the user type is the class that the method is member of.

Here is a class that will parse a decorated name, and print its declaration :) Have fun hooking C++ DLLs :)

CPPFunc.c
CPPFunc.h

Share

Dump exception in Windows

Dumping exception information in Windows applications

Had to make a Windows application dump exception info into a file for debugging purposes. Generally MS provies a prety neat function for it – GetExceptionInformation. One tricky thing was getting the module file name of the process that generated the exception – I had to do VirtualQuery on the exception address, then use the mbi.AllocationBase as a module handle (didn’t figure that out myself, googled for it of course).

Anyway, since I lost more then 30 minutes for it I decided to share it. Use this source and the exception handle your main function like this:

int _tmain(int argc, _TCHAR* argv[])
{

__try
{
}
__except( GetExceptionInfo( GetExceptionInformation(), “error.log” ), EXCEPTION_EXECUTE_HANDLER )
{
}

}

This way, when an exception occurs a file error.log will be generated that looks like this:

Exception Code: C0000005, Address: 00401646
Module: C:\DUMP\DEBUG\DUMP.EXE
Registers:
EAX:00000000, EBX:0063F6B4, ECX:0063F644, EDX:00410078, ESI:000086D8, EDI:0063F668
SS:00000167, ESP:0063F62C, EBP:0063F654, CS:0000015F, EIP:00401646, Flags:00010246
DS:00000167, ES:00000167, FS:00003CD7, GS:00000000
Stack:
0063F668 000086D8 0063F6B4 0063FCF0 0063F62C 0063F45C 0063F69C 00401B48
004051C8 00000000 0063F660 5F43507B 0063FCF0 0063F680 BFF7363B 00000250

Share