I recently had a problem at work where an application failed if the user tried to use UNC paths in a application that was ran as a service.

This service was written in C# that called into C DLL. Not only that, but the DLL was written in VC6.

So after confirming I could recreate the bug I removed the service and installed the debug version. I tested again and it was still there. I then added System.Diagnostics.Debugger.Break to the code and stepped in and through until I got to the calls to the DLL. The call stepped straight over. Hmm.

  • Debug build of the DLL: Check.
  • PDB file: Check.
  • Step into unmanaged code: Checked.
  • Debugging option: Mixed.

So what next. Maybe it wasn’t picking up the debug DLL.  So I went around and deleted every other version of the DLL. Didn’t fix it and broke most of the support apps.  Maybe it was a weird VS2K5/VC6 interaction.  So I rebuilt the library in Visual Studio but it still failed.

I could see the problematic code, but I couldn’t step in to see what the parameters were when it was there. So I created a small console app and transplanted in the problem code and called it. Worked as expected. Which brought up the idea that something was changing the parameters – but why, where and again why?! So the simple console app was extended to call the dll with every single call from the service in it with the same parameters, finally ending where the problem happened.

However it didn’t happen where I expected it to – the breakpoint I placed was never hit.  I thought that it wasn’t debugging properly still but it broke successfully if I placed a breakpoint at the start of the code. But if the code wasn’t being reached where it called CreateDirectory how comes there is a directory in the root of C:\ with the name of unc machine?

It turns out that it called a function earlier in the code than expected that uses mkdir – and the code that uses CreateDirectory never gets used due to the parameter tests that are done.

I looked at this code and thought about fixing it but there was over a hundred lines of strcat, strcpy, strtok and moving pointers around.  I decided that it was horribly broken and rewrite was in order.  So I looked on the net because this is a good case of reinventing the wheel.  Most sites, including my beloved StackOverflow, suggest using Boost.FileSystem which in my case is a non-starter. So I had a think about it and this is what I came up with after one false start:

BOOL CreateDirectories(char* path)
{
	BOOL status = TRUE;
	char* p;
	char temp_path[256];
	strcpy(temp_path, path);
	do {
		p = strrchr(temp_path, '\\');
		*p = '\0';
	} while (!SetCurrentDirectory(temp_path));
	do {
		p = strchr(temp_path, '\0');
		*p = '\\';
		status = CreateDirectory(temp_path);// do not check because this will fail on 'too\\many_slashes'
	} while (strlen(temp_path) < strlen(path));
	return status;
}

Now you can get away with removing the temp_path but I copied the original string to be safe, and I should of used MAX_PATH instead of hard-coding 256 but I think the code is quite elegant (though the WordPress formatting doesn’t really do it justice).

There’s a warning there – not to compare against the status in the while clause as having two slashes instead of one will prematurely cause the function to exit. Ignore the error that the function returns (ERROR_ALREADY_EXISTS) and the following time through it will continue to create the directories.