Workaround for VS2013

- Workaround for cl.exe deadlock for VS2013.

In wine environment, cl.exe sometimes tries to call EnterCriticalSection
with zero-cleared CRITICAL_SECTION. Wine thinks it so that someone has already
taken a lock, so cl.exe is stopped to wait for lock which no one holds.

If someone has taken a lock, RecursionCount should be 1. So zero-cleared
CriticalSection should mean no one holds a lock now. Thus, it should be OK
to allow cl.exe to enter a critical section for workaround.

- cl.exe for VS2013 sometimes cannot find headers.

For example,
  'C:\foo1.h': can be found
  'C:\foo12.h' : cannot be found
  'C:\foo123.h' : can be found.

When long_nameW is copied with memcpy to filename, wine sometimes copy
garbage characters. So, cl.exe tried finding 'C:\foo1.hh', 'C:\foo123.hi'
or something.

In this workaround, we initialize long_nameW with zero.

Change-Id: Ie2ddafa01920a298d046d0f98b860f3ff0f7a25c
diff --git a/dlls/ntdll/critsection.c b/dlls/ntdll/critsection.c
index d374916..3abc9b4 100644
--- a/dlls/ntdll/critsection.c
+++ b/dlls/ntdll/critsection.c
@@ -507,6 +507,18 @@
     return ret;
 }
 
+static BOOL IsAllZero(const void* begin, size_t size)
+{
+    const char* m = begin;
+    int i;
+
+    for (i = 0; i < size; ++i) {
+        if (m[i] != 0)
+            return FALSE;
+    }
+
+    return TRUE;
+}
 
 /***********************************************************************
  *           RtlEnterCriticalSection   (NTDLL.@)
@@ -527,6 +539,25 @@
  */
 NTSTATUS WINAPI RtlEnterCriticalSection( RTL_CRITICAL_SECTION *crit )
 {
+    // VS2013 cl.exe calls this with zero cleared crit.
+    // As far as we examined, this does not happen in real Windows.
+    // So maybe there is a wine bug that causes this. However, I have no idea
+    // about what causes this.
+    // Let's allow it to enter critical section for workaround.
+    if (IsAllZero(crit, sizeof(RTL_CRITICAL_SECTION))) {
+        if (interlocked_cmpxchg(&crit->SpinCount, 4000, 0) == 0) {
+            // OK. SpinCount was 0, and now 4000.
+            crit->LockCount = -1;
+        }
+
+        // When interlocked_cmpxchg was failed, someone changed SpinCount
+        // after IsAllZero(). With this workaround, someone will change or
+        // has changed crit->LockCount to -1. Leaving LockCount as is so that
+        // this thread (or the other thread) will wait for lock release.
+        // In usual case, cl.exe will return critical section with zero-cleared
+        // crit only once. So this shouldn't happen, though.
+    }
+
     if (crit->SpinCount)
     {
         ULONG count;
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
index cd2ee90..eeff643 100644
--- a/dlls/ntdll/directory.c
+++ b/dlls/ntdll/directory.c
@@ -1255,7 +1255,7 @@
     union file_directory_info *info;
     int i, long_len, short_len, total_len;
     struct stat st;
-    WCHAR long_nameW[MAX_DIR_ENTRY_LEN];
+    WCHAR long_nameW[MAX_DIR_ENTRY_LEN] = { (WCHAR)0 };
     WCHAR short_nameW[12];
     WCHAR *filename;
     UNICODE_STRING str;