Index: trunk/src/kmk/kmkbuiltin/mscfakes.h
===================================================================
--- trunk/src/kmk/kmkbuiltin/mscfakes.h	(revision 2710)
+++ trunk/src/kmk/kmkbuiltin/mscfakes.h	(revision 2713)
@@ -40,4 +40,5 @@
 #include <direct.h>
 #include "nt/ntstat.h"
+#include "nt/ntunlink.h"
 #if defined(MSC_DO_64_BIT_IO) && _MSC_VER >= 1400 /* We want 64-bit file lengths here when possible. */
 # define off_t __int64
Index: trunk/src/kmk/kmkbuiltin/rm.c
===================================================================
--- trunk/src/kmk/kmkbuiltin/rm.c	(revision 2710)
+++ trunk/src/kmk/kmkbuiltin/rm.c	(revision 2713)
@@ -67,6 +67,12 @@
 # include "haikufakes.h"
 #endif
-#ifdef _MSC_VER
-# include "mscfakes.h"
+#ifdef KBUILD_OS_WINDOWS
+# ifdef _MSC_VER
+#  include "mscfakes.h"
+# endif
+# include "nt/ntunlink.h"
+  /* Use the special unlink implementation to do rmdir too. */
+# undef  rmdir
+# define rmdir(a_pszPath) 	birdUnlinkForced(a_pszPath)
 #endif
 #if defined(__OS2__) || defined(_MSC_VER)
@@ -77,5 +83,5 @@
 #include "kbuild_protection.h"
 
-#if defined(__EMX__) || defined(_MSC_VER)
+#if defined(__EMX__) || defined(KBUILD_OS_WINDOWS)
 # define IS_SLASH(ch)   ( (ch) == '/' || (ch) == '\\' )
 # define HAVE_DOS_PATHS 1
@@ -100,4 +106,7 @@
 
 static int dflag, eval, fflag, iflag, Pflag, vflag, Wflag, stdin_ok;
+#ifdef KBUILD_OS_WINDOWS
+static int fUseNtDeleteFile;
+#endif
 static uid_t uid;
 
@@ -114,4 +123,7 @@
     { "disable-full-protection",			no_argument, 0, 266 },
     { "protection-depth",				required_argument, 0, 267 },
+#ifdef KBUILD_OS_WINDOWS
+    { "nt-delete-file",					no_argument, 0, 268 },
+#endif
     { 0, 0,	0, 0 },
 };
@@ -149,4 +161,7 @@
 	argv0 = argv[0];
 	dflag = eval = fflag = iflag = Pflag = vflag = Wflag = stdin_ok = 0;
+#ifdef KBUILD_OS_WINDOWS
+	fUseNtDeleteFile = 0;
+#endif
 	uid = 0;
 	kBuildProtectionInit(&g_ProtData);
@@ -215,4 +230,9 @@
 			}
 			break;
+#ifdef KBUILD_OS_WINDOWS
+		case 268:
+			fUseNtDeleteFile = 1;
+			break;
+#endif
 		case '?':
 		default:
@@ -404,10 +424,8 @@
 					if (!rm_overwrite(p->fts_accpath, NULL))
 						continue;
+#ifdef KBUILD_OS_WINDOWS
+				rval = birdUnlinkForcedFast(p->fts_accpath);
+#else
 				rval = unlink(p->fts_accpath);
-#ifdef _MSC_VER
-				if (rval != 0) {
-    					chmod(p->fts_accpath, 0777);
-					rval = unlink(p->fts_accpath);
-				}
 #endif
 
@@ -499,9 +517,5 @@
 				rval = undelete(f);
 				operation = "undelete";
-#ifndef _MSC_VER
 			} else if (S_ISDIR(sb.st_mode)) {
-#else
-			} else if (S_ISDIR(sb.st_mode) || sb.st_dirsymlink) {
-#endif
 				rval = rmdir(f);
 				operation = "rmdir";
@@ -510,12 +524,16 @@
 					if (!rm_overwrite(f, &sb))
 						continue;
+#ifndef KBUILD_OS_WINDOWS
 				rval = unlink(f);
-#ifdef _MSC_VER
-				if (rval != 0) {
-					chmod(f, 0777);
-					rval = unlink(f);
+				operation = "unlink";
+#else
+				if (fUseNtDeleteFile) {
+					rval = birdUnlinkForcedFast(f);
+					operation = "NtDeleteFile";
+				} else {
+					rval = birdUnlinkForced(f);
+					operation = "unlink";
 				}
 #endif
-				operation = "unlink";
 			}
 		}
Index: trunk/src/lib/Makefile.kmk
===================================================================
--- trunk/src/lib/Makefile.kmk	(revision 2710)
+++ trunk/src/lib/Makefile.kmk	(revision 2713)
@@ -46,5 +46,6 @@
        nt/nthlpfs.c \
        nt/ntdir.c \
-       nt/ntstat.c
+       nt/ntstat.c \
+       nt/ntunlink.c
 kUtil_SOURCES.solaris = \
 	restartable-syscall-wrappers.c
Index: trunk/src/lib/nt/nthlp.h
===================================================================
--- trunk/src/lib/nt/nthlp.h	(revision 2710)
+++ trunk/src/lib/nt/nthlp.h	(revision 2713)
@@ -59,5 +59,9 @@
                               ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
                               MY_UNICODE_STRING *pNameUniStr);
+MY_NTSTATUS birdOpenFileUniStr(MY_UNICODE_STRING *pNtPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
+                               ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
+                               HANDLE *phFile);
 void        birdCloseFile(HANDLE hFile);
+int         birdDosToNtPath(const char *pszPath, MY_UNICODE_STRING *pNtPath);
 void        birdFreeNtPath(MY_UNICODE_STRING *pNtPath);
 
Index: trunk/src/lib/nt/nthlpcore.c
===================================================================
--- trunk/src/lib/nt/nthlpcore.c	(revision 2710)
+++ trunk/src/lib/nt/nthlpcore.c	(revision 2713)
@@ -45,4 +45,5 @@
 MY_NTSTATUS (WINAPI *g_pfnNtCreateFile)(PHANDLE, MY_ACCESS_MASK, MY_OBJECT_ATTRIBUTES *, MY_IO_STATUS_BLOCK *,
                                         PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);
+MY_NTSTATUS (WINAPI *g_pfnNtDeleteFile)(MY_OBJECT_ATTRIBUTES *);
 MY_NTSTATUS (WINAPI *g_pfnNtQueryInformationFile)(HANDLE, MY_IO_STATUS_BLOCK *, PVOID, LONG, MY_FILE_INFORMATION_CLASS);
 MY_NTSTATUS (WINAPI *g_pfnNtQueryVolumeInformationFile)(HANDLE, MY_IO_STATUS_BLOCK *, PVOID, LONG, MY_FS_INFORMATION_CLASS);
@@ -50,4 +51,5 @@
                                                 PVOID, ULONG, MY_FILE_INFORMATION_CLASS, BOOLEAN,
                                                 MY_UNICODE_STRING *, BOOLEAN);
+MY_NTSTATUS (WINAPI *g_pfnNtSetInformationFile)(HANDLE, MY_IO_STATUS_BLOCK *, PVOID, LONG, MY_FILE_INFORMATION_CLASS);
 BOOLEAN     (WINAPI *g_pfnRtlDosPathNameToNtPathName_U)(PCWSTR, MY_UNICODE_STRING *, PCWSTR *, MY_RTL_RELATIVE_NAME_U *);
 MY_NTSTATUS (WINAPI *g_pfnRtlAnsiStringToUnicodeString)(MY_UNICODE_STRING *, MY_ANSI_STRING const *, BOOLEAN);
@@ -62,7 +64,9 @@
     { (FARPROC *)&g_pfnNtClose,                         "NtClose" },
     { (FARPROC *)&g_pfnNtCreateFile,                    "NtCreateFile" },
+    { (FARPROC *)&g_pfnNtDeleteFile,                    "NtDeleteFile" },
     { (FARPROC *)&g_pfnNtQueryInformationFile,          "NtQueryInformationFile" },
     { (FARPROC *)&g_pfnNtQueryVolumeInformationFile,    "NtQueryVolumeInformationFile" },
     { (FARPROC *)&g_pfnNtQueryDirectoryFile,            "NtQueryDirectoryFile" },
+    { (FARPROC *)&g_pfnNtSetInformationFile,            "NtSetInformationFile" },
     { (FARPROC *)&g_pfnRtlDosPathNameToNtPathName_U,    "RtlDosPathNameToNtPathName_U" },
     { (FARPROC *)&g_pfnRtlAnsiStringToUnicodeString,    "RtlAnsiStringToUnicodeString" },
@@ -137,4 +141,7 @@
     {
         /* EPERM            =  1 */
+        case STATUS_CANNOT_DELETE:
+            errno = EPERM;
+            break;
         /* ENOENT           =  2 */
         case STATUS_NOT_FOUND:
Index: trunk/src/lib/nt/nthlpfs.c
===================================================================
--- trunk/src/lib/nt/nthlpfs.c	(revision 2710)
+++ trunk/src/lib/nt/nthlpfs.c	(revision 2713)
@@ -78,5 +78,5 @@
 
 
-static int birdDosToNtPath(const char *pszPath, MY_UNICODE_STRING *pNtPath)
+int birdDosToNtPath(const char *pszPath, MY_UNICODE_STRING *pNtPath)
 {
     MY_NTSTATUS         rcNt;
@@ -128,7 +128,7 @@
 
 
-static MY_NTSTATUS birdOpenFileInternal(MY_UNICODE_STRING *pNtPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
-                                        ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
-                                        HANDLE *phFile)
+MY_NTSTATUS birdOpenFileUniStr(MY_UNICODE_STRING *pNtPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
+                               ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
+                               HANDLE *phFile)
 {
     MY_IO_STATUS_BLOCK      Ios;
@@ -203,6 +203,6 @@
     {
         HANDLE hFile;
-        rcNt = birdOpenFileInternal(&NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
-                                    fCreateDisposition, fCreateOptions, fObjAttribs, &hFile);
+        rcNt = birdOpenFileUniStr(&NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
+                                  fCreateDisposition, fCreateOptions, fObjAttribs, &hFile);
         if (MY_NT_SUCCESS(rcNt))
         {
@@ -278,6 +278,6 @@
                  */
                 HANDLE hFile;
-                rcNt = birdOpenFileInternal(&NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
-                                            fCreateDisposition, fCreateOptions, fObjAttribs, &hFile);
+                rcNt = birdOpenFileUniStr(&NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
+                                          fCreateDisposition, fCreateOptions, fObjAttribs, &hFile);
                 if (MY_NT_SUCCESS(rcNt))
                 {
Index: trunk/src/lib/nt/ntstuff.h
===================================================================
--- trunk/src/lib/nt/ntstuff.h	(revision 2710)
+++ trunk/src/lib/nt/ntstuff.h	(revision 2713)
@@ -199,4 +199,10 @@
 /** The sizeof(MY_FILE_NAMES_INFORMATION) without the FileName. */
 #define MIN_SIZEOF_MY_FILE_ID_FULL_DIR_INFORMATION  ( (size_t)&((MY_FILE_ID_FULL_DIR_INFORMATION *)0)->FileName )
+
+
+typedef struct MY_FILE_DISPOSITION_INFORMATION
+{
+    BOOLEAN         DeleteFile;
+} MY_FILE_DISPOSITION_INFORMATION;
 
 
@@ -361,4 +367,5 @@
 extern MY_NTSTATUS (WINAPI * g_pfnNtCreateFile)(PHANDLE, MY_ACCESS_MASK, MY_OBJECT_ATTRIBUTES *, MY_IO_STATUS_BLOCK *,
                                                 PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);
+extern MY_NTSTATUS (WINAPI * g_pfnNtDeleteFile)(MY_OBJECT_ATTRIBUTES *);
 extern MY_NTSTATUS (WINAPI * g_pfnNtQueryInformationFile)(HANDLE, MY_IO_STATUS_BLOCK *,
                                                           PVOID, LONG, MY_FILE_INFORMATION_CLASS);
@@ -368,4 +375,5 @@
                                                         PVOID, ULONG, MY_FILE_INFORMATION_CLASS, BOOLEAN,
                                                         MY_UNICODE_STRING *, BOOLEAN);
+extern MY_NTSTATUS (WINAPI * g_pfnNtSetInformationFile)(HANDLE, MY_IO_STATUS_BLOCK *, PVOID, LONG, MY_FILE_INFORMATION_CLASS);
 extern BOOLEAN     (WINAPI * g_pfnRtlDosPathNameToNtPathName_U)(PCWSTR, MY_UNICODE_STRING *, PCWSTR *, MY_RTL_RELATIVE_NAME_U *);
 extern MY_NTSTATUS (WINAPI * g_pfnRtlAnsiStringToUnicodeString)(MY_UNICODE_STRING *, MY_ANSI_STRING const *, BOOLEAN);
Index: trunk/src/lib/nt/ntunlink.c
===================================================================
--- trunk/src/lib/nt/ntunlink.c	(revision 2713)
+++ trunk/src/lib/nt/ntunlink.c	(revision 2713)
@@ -0,0 +1,171 @@
+/* $Id$ */
+/** @file
+ * MSC + NT unlink and variations.
+ */
+
+/*
+ * Copyright (c) 2005-2013 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <stdio.h>
+#include <errno.h>
+#include <malloc.h>
+
+#include "ntstuff.h"
+#include "nthlp.h"
+
+
+static MY_NTSTATUS birdMakeWritable(MY_UNICODE_STRING *pNtPath)
+{
+    MY_NTSTATUS rcNt;
+    HANDLE      hFile;
+
+    rcNt = birdOpenFileUniStr(pNtPath,
+                              FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
+                              FILE_ATTRIBUTE_NORMAL,
+                              FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+                              FILE_OPEN,
+                              FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
+                              OBJ_CASE_INSENSITIVE,
+                              &hFile);
+    if (MY_NT_SUCCESS(rcNt))
+    {
+        MY_FILE_BASIC_INFORMATION   BasicInfo;
+        MY_IO_STATUS_BLOCK          Ios;
+        DWORD                       dwAttr;
+
+        Ios.Information = -1;
+        Ios.u.Status    = -1;
+        rcNt = g_pfnNtQueryInformationFile(hFile, &Ios, &BasicInfo, sizeof(BasicInfo), MyFileBasicInformation);
+
+        if (MY_NT_SUCCESS(rcNt) && MY_NT_SUCCESS(Ios.u.Status))
+            dwAttr = BasicInfo.FileAttributes & ~FILE_ATTRIBUTE_READONLY;
+        else
+            dwAttr = FILE_ATTRIBUTE_NORMAL;
+        memset(&BasicInfo, 0, sizeof(BasicInfo));
+        BasicInfo.FileAttributes = dwAttr;
+
+        Ios.Information = -1;
+        Ios.u.Status    = -1;
+        rcNt = g_pfnNtSetInformationFile(hFile, &Ios, &BasicInfo, sizeof(BasicInfo), MyFileBasicInformation);
+
+        birdCloseFile(hFile);
+    }
+
+    return rcNt;
+}
+
+
+static int birdUnlinkInternal(const char *pszFile, int fReadOnlyToo, int fFast)
+{
+    MY_UNICODE_STRING   NtPath;
+    int                 rc;
+
+    rc = birdDosToNtPath(pszFile, &NtPath);
+    if (rc == 0)
+    {
+        MY_NTSTATUS rcNt;
+        if (fFast)
+        {
+            /* This uses FILE_DELETE_ON_CLOSE. Probably only suitable when in a hurry... */
+            MY_OBJECT_ATTRIBUTES ObjAttr;
+            MyInitializeObjectAttributes(&ObjAttr, &NtPath, OBJ_CASE_INSENSITIVE, NULL /*hRoot*/, NULL /*pSecAttr*/);
+            rcNt = g_pfnNtDeleteFile(&ObjAttr);
+
+            /* In case some file system does things differently than NTFS. */
+            if (rcNt == STATUS_CANNOT_DELETE)
+            {
+                birdMakeWritable(&NtPath);
+                rcNt = g_pfnNtDeleteFile(&ObjAttr);
+            }
+        }
+        else
+        {
+            /* Use the set information stuff. Probably more reliable. */
+            HANDLE hFile;
+            int    fMayTryAgain = 1;
+            for (;;)
+            {
+                rcNt = birdOpenFileUniStr(&NtPath,
+                                          DELETE,
+                                          FILE_ATTRIBUTE_NORMAL,
+                                          FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+                                          FILE_OPEN,
+                                          FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT,
+                                          OBJ_CASE_INSENSITIVE,
+                                          &hFile);
+                if (MY_NT_SUCCESS(rcNt))
+                {
+                    MY_FILE_DISPOSITION_INFORMATION DispInfo;
+                    MY_IO_STATUS_BLOCK              Ios;
+
+                    DispInfo.DeleteFile = TRUE;
+
+                    Ios.Information = -1;
+                    Ios.u.Status    = -1;
+
+                    rcNt = g_pfnNtSetInformationFile(hFile, &Ios, &DispInfo, sizeof(DispInfo), MyFileDispositionInformation);
+
+                    birdCloseFile(hFile);
+                }
+                if (rcNt != STATUS_CANNOT_DELETE || !fMayTryAgain)
+                    break;
+
+                fMayTryAgain = 0;
+                birdMakeWritable(&NtPath);
+            }
+        }
+
+        birdFreeNtPath(&NtPath);
+
+        if (MY_NT_SUCCESS(rcNt))
+            rc = 0;
+        else
+            rc = birdSetErrnoFromNt(rcNt);
+    }
+    return rc;
+}
+
+
+int birdUnlink(const char *pszFile)
+{
+    return birdUnlinkInternal(pszFile, 0 /*fReadOnlyToo*/, 0 /*fFast*/);
+}
+
+
+int birdUnlinkForced(const char *pszFile)
+{
+    return birdUnlinkInternal(pszFile, 1 /*fReadOnlyToo*/, 0 /*fFast*/);
+}
+
+
+int birdUnlinkForcedFast(const char *pszFile)
+{
+    return birdUnlinkInternal(pszFile, 1 /*fReadOnlyToo*/, 1 /*fFast*/);
+}
+
Index: trunk/src/lib/nt/ntunlink.h
===================================================================
--- trunk/src/lib/nt/ntunlink.h	(revision 2713)
+++ trunk/src/lib/nt/ntunlink.h	(revision 2713)
@@ -0,0 +1,44 @@
+/* $Id$ */
+/** @file
+ * MSC + NT unlink and variations.
+ */
+
+/*
+ * Copyright (c) 2005-2013 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
+ */
+
+#ifndef ___nt_ntunlink_h
+#define ___nt_ntunlink_h
+
+#include "nttypes.h"
+
+int birdUnlink(const char *pszFile);
+int birdUnlinkForced(const char *pszFile);
+int birdUnlinkForcedFast(const char *pszFile);
+
+#undef  unlink
+#define unlink(a_pszPath)     birdUnlinkForced(a_pszPath)
+
+#endif
+
