Index: VHD.cpp
===================================================================
--- VHD.cpp	(revision 38898)
+++ VHD.cpp	(working copy)
@@ -246,7 +246,198 @@
 *   Internal Functions                                                         *
 *******************************************************************************/
 
+#ifdef RT_OS_WINDOWS
 
+#include <ctype.h>
+
+int DetermineDosPathNameType(const char *buf, int len)
+{
+	int type;
+
+	if ( len < 2 || buf[0] != '\\' && buf[0] != '/' )
+	{
+		if ( len >= 4 && buf[0] && buf[1] == ':' )
+		{
+			if ( len < 6 || buf[2] != '\\' && buf[2] != '/' )
+				type = 3;
+			else
+				type = 2;
+		}
+		else
+		{
+			type = 5;
+		}
+	}
+	else
+	{
+		if ( len < 4 || buf[1] != '\\' && buf[1] != '/' )
+		{
+			type = 4;
+		}
+		else
+		{
+			if ( len < 6 || buf[2] != '.' && buf[2] != '?' )
+			{
+				type = 1;
+			}
+			else
+			{
+				if ( len < 8 || buf[3] != '\\' && buf[3] != '/' )
+				{
+					if ( len == 6 )
+						type = 7;
+					else
+						type = 1;
+				}
+				else
+				{
+					type = 6;
+				}
+			}
+		}
+	}
+
+	return type;
+}
+
+int GetLongPathAgnosticCompareBaseIndex(const char *path)
+{
+	int type;
+	int len;
+	int idx;
+
+	len = strlen(path);
+	type = DetermineDosPathNameType(path, len);
+	switch (type)
+	{
+	  case 1:
+		  idx = 1;
+		  break;
+	  case 2:
+		  idx = 0;
+		  break;
+	  case 6:
+		  if ( len <= 7
+			|| toupper(path[4]) != 'U'
+			|| toupper(path[5]) != 'N'
+			|| toupper(path[6]) != 'C' )
+			  idx = 4;
+		  else
+			  idx = 7;
+		  break;
+	  default:
+		  idx = 0;
+		  break;
+	}
+	return idx;
+}
+
+int AbsolutePathNameToRelative(const char *Base, const char *Path, char **pOutRelativePath)
+{		
+	int length;
+	char *RelativePath;
+	int idx;
+	const char *buf1;
+	int buflen1;
+	int idx2;
+	const char *buf2;
+	int buflen2;	
+	int i, m, n;
+
+	if (Base == NULL || Path == NULL)
+		return VERR_INVALID_PARAMETER;
+
+	int err = VINF_SUCCESS;
+	int baselen = strlen(Base);
+	int pathlen = strlen(Path);
+
+	m = -1;
+	n = 0;
+	RelativePath = NULL;
+	
+	idx = GetLongPathAgnosticCompareBaseIndex(Base);
+	buf1 = Base + idx;
+	buflen1 = baselen - idx;
+
+	idx2 = GetLongPathAgnosticCompareBaseIndex(Path);
+	buf2 = Path + idx2;
+	buflen2 = pathlen - idx2;
+	for ( i = 0; i < buflen1; ++i )
+	{
+	  if ( i >= buflen2 )
+		  break;
+	  
+	  if ( toupper(buf1[i]) != toupper(buf2[i]) )
+		  break;
+
+	  if ( buf1[i] == '\\' )
+		  m = i;
+	}
+	if ( m == -1 )
+	{
+		err = VERR_NOT_IMPLEMENTED;
+		goto Exit;
+	}
+	while ( i < buflen1 )
+	{
+		if ( buf1[i] == '\\' )
+			++n;
+		++i;
+	}
+	length = buflen2 - m - 1;
+	if ( n )
+		length += 3 * n;
+	else
+		length += 1;
+	
+	if ( length > 0x10000 )
+	{
+		err = VERR_INVALID_PARAMETER;
+		goto Exit;
+	}
+	RelativePath = (char *)RTMemAlloc(length);
+	if (RelativePath == NULL)
+	{
+		err = VERR_NO_MEMORY;
+		goto Exit;
+	}
+	
+	RelativePath[0] = 0;
+	if ( n )
+	{
+		while ( n > 0 )
+		{
+			strcat(RelativePath, "..\\");			
+			--n;
+		}
+	}
+	else
+	{
+		strcat(RelativePath, ".\\");		
+	}
+
+	const char *buf = buf2 + m + 1;
+	int len = buflen2 - (m + 1);
+	
+	pathlen = strlen(RelativePath);
+	memcpy(RelativePath+pathlen, buf, len);
+	RelativePath[pathlen + len] = 0;
+
+Exit:
+	if (err != VINF_SUCCESS)
+	{
+		if ( RelativePath )
+			RTMemFree(RelativePath);
+
+		RelativePath = NULL;
+	}
+
+	*pOutRelativePath = RelativePath;
+
+	return err;
+}
+#endif /* RT_OS_WINDOWS */
+
 /**
  * Internal: Compute and update header checksum.
  */
@@ -331,7 +522,51 @@
             break;
         case VHD_PLATFORM_CODE_W2RU:
             /* Update unicode relative name. */
+#ifdef RT_OS_WINDOWS
+		{
+			char *relative_path, *base;
+			pszTmp = (char*)RTMemTmpAllocZ(cbMaxLen);
+            if (!pszTmp)
+            {
+                rc = VERR_NO_MEMORY;
+                goto out;
+            }
+            rc = RTPathAbs(pszFilename, pszTmp, cbMaxLen);
+            if (RT_FAILURE(rc))
+            {
+                RTMemTmpFree(pszTmp);
+                goto out;
+            }
+			base = (char*)RTMemTmpAllocZ(cbMaxLen);
+            if (!base)
+            {
+				RTMemTmpFree(pszTmp);
+                rc = VERR_NO_MEMORY;
+                goto out;
+            }
+            rc = RTPathAbs(pImage->pszFilename, base, cbMaxLen);
+            if (RT_FAILURE(rc))
+            {
+				RTMemTmpFree(pszTmp);
+                RTMemTmpFree(base);
+                goto out;
+            }
+			rc = AbsolutePathNameToRelative(base, pszTmp, &relative_path);
+			RTMemTmpFree(pszTmp);
+			RTMemTmpFree(base);
+			if (RT_SUCCESS(rc))
+			{
+				rc = vhdFilenameToUtf16(relative_path, (uint16_t *)pvBuf, cbMaxLen, &cb, false);
+				RTMemTmpFree(relative_path);
+			}
+			else
+			{
+				rc = vhdFilenameToUtf16(pszFilename, (uint16_t *)pvBuf, cbMaxLen, &cb, false);
+			}
+		}
+#else
             rc = vhdFilenameToUtf16(pszFilename, (uint16_t *)pvBuf, cbMaxLen, &cb, false);
+#endif
             if (RT_FAILURE(rc))
                 goto out;
             pLocator->u32DataLength = RT_H2BE_U32(cb);
