* Sync up to trunk head (r64894).
authorAmine Khaldi <amine.khaldi@reactos.org>
Wed, 22 Oct 2014 17:07:43 +0000 (17:07 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Wed, 22 Oct 2014 17:07:43 +0000 (17:07 +0000)
svn path=/branches/shell-experiments/; revision=64895

111 files changed:
CMakeLists.txt
base/applications/cmdutils/help/help.c
base/applications/msconfig/srvpage.c
base/applications/msconfig/startuppage.c
base/applications/mscutils/servman/export.c
base/applications/mscutils/servman/mainwnd.c
base/applications/mscutils/servman/progress.c
base/applications/mscutils/servman/propsheet_general.c
base/applications/mscutils/servman/query.c
base/applications/mscutils/servman/stop_dependencies.c
base/applications/network/net/CMakeLists.txt
base/applications/network/net/cmdAccounts.c
base/applications/network/net/cmdLocalGroup.c [new file with mode: 0644]
base/applications/network/net/lang/en-US.rc
base/applications/network/net/lang/ro-RO.rc
base/applications/network/net/lang/ru-RU.rc
base/applications/network/net/main.c
base/applications/network/net/net.h
base/applications/taskmgr/column.c
base/applications/taskmgr/graphctl.c
base/applications/taskmgr/graphctl.h
base/applications/taskmgr/taskmgr.c
base/shell/cmd/copy.c
base/shell/cmd/internal.c
base/shell/cmd/locale.c
base/shell/cmd/move.c
base/shell/cmd/replace.c
base/shell/explorer/desktop/desktop.h
base/system/regsvr32/regsvr32.c
configure.cmd
dll/keyboard/CMakeLists.txt
dll/win32/devmgr/devprblm.c
dll/win32/kernel32/client/file/move.c
dll/win32/kernel32/winnls/string/casemap.c
dll/win32/kernel32/winnls/string/format_msg.c
dll/win32/kernel32/winnls/string/lang.c
dll/win32/setupapi/devclass.c
dll/win32/ws2_32_new/src/addrinfo.c
drivers/filesystems/fastfat/close.c
drivers/filesystems/fastfat/create.c
drivers/filesystems/fastfat/dirwr.c
drivers/filesystems/fastfat/fcb.c
drivers/filesystems/fastfat/finfo.c
drivers/filesystems/fastfat/vfat.h
drivers/filesystems/npfs/create.c
drivers/filesystems/npfs/secursup.c
drivers/filesystems/npfs/seinfo.c
drivers/filesystems/ntfs/dirctl.c
drivers/filesystems/ntfs/misc.c
drivers/filesystems/ntfs/ntfs.h
drivers/network/afd/afd/bind.c
drivers/network/afd/afd/connect.c
drivers/network/afd/afd/listen.c
drivers/network/afd/afd/main.c
drivers/network/afd/afd/read.c
drivers/network/afd/afd/tdi.c
drivers/network/afd/afd/write.c
drivers/network/afd/include/afd.h
drivers/network/afd/include/tdi_proto.h
drivers/storage/ide/uniata/id_ata.cpp
drivers/storage/ide/uniata/id_dma.cpp
drivers/storage/ide/uniata/id_sata.cpp
drivers/storage/ide/uniata/uniata_ver.h
include/reactos/mc/bugcodes.mc
lib/3rdparty/strmbase/pin.c
lib/3rdparty/strmbase/transform.c
lib/drivers/ip/transport/tcp/event.c
lib/drivers/sound/mmixer/controls.c
lib/drivers/sound/mmixer/midi.c
lib/drivers/sound/mmixer/mixer.c
lib/fast486/common.c
lib/fast486/common.inl
lib/fast486/debug.c
lib/fast486/extraops.c
lib/fast486/fast486.c
lib/fast486/opcodes.c
lib/fast486/opgroups.c
lib/fast486/opgroups.h
lib/rtl/bitmap.c
media/doc/README.WINE
ntoskrnl/include/internal/mm.h
ntoskrnl/ke/bug.c
ntoskrnl/mm/ARM3/expool.c
ntoskrnl/mm/ARM3/pagfault.c
ntoskrnl/mm/ARM3/special.c
subsystems/ntvdm/int32.c
win32ss/drivers/videoprt/registry.c
win32ss/gdi/ntgdi/freetype.c
win32ss/gdi/ntgdi/misc.h
win32ss/include/ntuser.h
win32ss/user/ntuser/callproc.c
win32ss/user/ntuser/class.c
win32ss/user/ntuser/cursoricon.c
win32ss/user/ntuser/cursoricon.h
win32ss/user/ntuser/cursoricon_new.c
win32ss/user/ntuser/dce.h
win32ss/user/ntuser/defwnd.c
win32ss/user/ntuser/desktop.c
win32ss/user/ntuser/display.c
win32ss/user/ntuser/main.c
win32ss/user/ntuser/message.c
win32ss/user/ntuser/msgqueue.c
win32ss/user/ntuser/object.c
win32ss/user/ntuser/object.h
win32ss/user/ntuser/painting.c
win32ss/user/ntuser/painting.h
win32ss/user/ntuser/windc.c
win32ss/user/ntuser/window.c
win32ss/user/user32/misc/desktop.c
win32ss/user/user32/windows/class.c
win32ss/user/user32/windows/defwnd.c

index a5f5645..152d0c0 100644 (file)
@@ -6,6 +6,11 @@ if(POLICY CMP0017)
     cmake_policy(SET CMP0017 OLD)
 endif()
 
+if(POLICY CMP0026)
+    # Allow use of the LOCATION property
+    cmake_policy(SET CMP0026 OLD)
+endif()
+
 project(REACTOS)
 
 # Versioning
index 668e930..24ac9d8 100644 (file)
@@ -16,6 +16,7 @@
 #include <winbase.h>
 #include <winuser.h>
 #include <wincon.h>
+#include <strsafe.h>
 
 #include "help.h"
 #include "resource.h"
@@ -135,9 +136,8 @@ int wmain(int argc, WCHAR* argv[])
     /*
      * Run "<command> /?" in the current command processor.
      */
-    wcsncpy(CmdLine, argv[1], CMDLINE_LENGTH - wcslen(CmdLine));
-    wcsncat(CmdLine, L" /?" , CMDLINE_LENGTH - wcslen(CmdLine));
-
+    StringCbPrintfW(CmdLine, sizeof(CmdLine), L"%ls /?", argv[1]);
+    
     _flushall();
     return _wsystem(CmdLine);
 }
index 4cfd62e..44870c0 100644 (file)
@@ -187,19 +187,16 @@ GetServices ( void )
                             return;
                         }
                     }
-                    if (pServiceFailureActions->cActions)
-                    {
-                        if (pServiceFailureActions->lpsaActions[0].Type == SC_ACTION_REBOOT)
-                        {
-                            LoadString(hInst, IDS_SERVICES_YES, szStatus, 128);
-                            item.pszText = szStatus;
-                            item.iSubItem = 1;
-                            SendMessage(hServicesListCtrl, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
-                        }
-                    }
 
                     if (pServiceFailureActions != NULL)
                     {
+                        if (pServiceFailureActions->cActions && pServiceFailureActions->lpsaActions[0].Type == SC_ACTION_REBOOT)
+                        {
+                                LoadString(hInst, IDS_SERVICES_YES, szStatus, 128);
+                                item.pszText = szStatus;
+                                item.iSubItem = 1;
+                                SendMessage(hServicesListCtrl, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
+                        }
                         HeapFree(GetProcessHeap(), 0, pServiceFailureActions);
                         pServiceFailureActions = NULL;
                     }
index 4d65a0f..e535893 100644 (file)
@@ -97,7 +97,11 @@ GetDisabledAutostartEntriesFromRegistry (TCHAR * szBasePath)
                 if (Data == NULL)
                     break;
 
-                RegEnumKeyEx(hKey, Index, szValueName, &dwValueLength, NULL, NULL, NULL, NULL);
+                if(RegEnumKeyEx(hKey, Index, szValueName, &dwValueLength, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
+                {
+                    HeapFree(GetProcessHeap(), 0, Data);
+                    continue;
+                }
                 _stprintf(szSubPath, _T("%s\\%s"), szBasePath, szValueName);
                 memset(&item, 0, sizeof(LV_ITEM));
                 item.mask = LVIF_TEXT;
index f637a5d..3df3c44 100644 (file)
@@ -52,7 +52,7 @@ SaveServicesToFile(PMAIN_WND_INFO Info,
     if(hFile != INVALID_HANDLE_VALUE)
     {
         TCHAR LVText[500];
-        TCHAR newl = _T('\n');
+        TCHAR newl[2] = {_T('\r'), _T('\n')};
         TCHAR tab = _T('\t');
         DWORD dwTextLength, dwWritten;
         INT NumListedServ = 0;
@@ -68,7 +68,7 @@ SaveServicesToFile(PMAIN_WND_INFO Info,
                                                    LVText,
                                                    i,
                                                    k);
-                if (LVText != NULL)
+                if (_tcslen(LVText))
                 {
                     WriteFile(hFile,
                               LVText,
@@ -84,8 +84,8 @@ SaveServicesToFile(PMAIN_WND_INFO Info,
                 }
             }
             WriteFile(hFile,
-                      &newl,
-                      sizeof(TCHAR),
+                      newl,
+                      sizeof(newl),
                       &dwWritten,
                       NULL);
         }
index 6823379..8291481 100644 (file)
@@ -204,9 +204,10 @@ VOID SetMenuAndButtonStates(PMAIN_WND_INFO Info)
                 SendMessage(Info->hTool, TB_SETSTATE, ID_RESTART,
                        (LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
             }
+        }
 
+        if(lpServiceConfig)
             HeapFree(GetProcessHeap(), 0, lpServiceConfig);
-        }
 
         if ( (Flags & SERVICE_ACCEPT_STOP) && (State == SERVICE_RUNNING) )
         {
index e3c2d6b..8c9c843 100644 (file)
@@ -167,9 +167,7 @@ CreateProgressDialog(HWND hParent,
                                 0,
                                 (LPARAM)lpProgStr);
 
-            HeapFree(GetProcessHeap(),
-                     0,
-                     lpProgStr);
+            LocalFree(lpProgStr);
         }
 
         /* Finally, show and update the progress dialog */
index 9c33a97..6bac4cd 100644 (file)
@@ -33,7 +33,6 @@ SetButtonStates(PSERVICEPROPSHEET dlgInfo,
     {
         hButton = GetDlgItem(hwndDlg, IDC_START);
         EnableWindow (hButton, TRUE);
-        HeapFree(GetProcessHeap(), 0, lpServiceConfig);
     }
     else if ( (Flags & SERVICE_ACCEPT_STOP) && (State == SERVICE_RUNNING) )
     {
@@ -46,6 +45,9 @@ SetButtonStates(PSERVICEPROPSHEET dlgInfo,
         EnableWindow (hButton, TRUE);
     }
 
+    if(lpServiceConfig)
+        HeapFree(GetProcessHeap(), 0, lpServiceConfig);
+
     hButton = GetDlgItem(hwndDlg, IDC_START_PARAM);
     EnableWindow(hButton, (State == SERVICE_STOPPED));
 
index 14a68e5..3a5e82c 100644 (file)
@@ -270,6 +270,7 @@ GetServiceList(PMAIN_WND_INFO Info,
         HeapFree(ProcessHeap,
                      0,
                      Info->pAllServices);
+        Info->pAllServices = NULL;
     }
 
     ScHandle = OpenSCManager(NULL,
@@ -319,7 +320,7 @@ GetServiceList(PMAIN_WND_INFO Info,
     if (ScHandle)
         CloseServiceHandle(ScHandle);
 
-    if (!bRet)
+    if (!bRet && Info->pAllServices)
     {
         HeapFree(ProcessHeap,
                  0,
index 559002c..99b60bb 100644 (file)
@@ -163,6 +163,8 @@ AddServiceNamesToStop(HWND hServiceListBox,
                          LB_ADDSTRING,
                          0,
                          (LPARAM)lpServiceConfig->lpDisplayName);
+
+            HeapFree(GetProcessHeap(), 0, lpServiceConfig);
         }
 
         /* Move onto the next string */
index a740d3a..c3507d6 100644 (file)
@@ -4,11 +4,12 @@ add_definitions(-D__USE_W32_SOCKETS)
 list(APPEND SOURCE
     main.c
     cmdAccounts.c
-    cmdStart.c
-    cmdStop.c
+    cmdContinue.c
     cmdHelpMsg.c
+    cmdLocalGroup.c
     cmdPause.c
-    cmdContinue.c
+    cmdStart.c
+    cmdStop.c
     help.c
     net.h)
 
index 456ac4c..c297da0 100644 (file)
@@ -24,7 +24,9 @@ cmdAccounts(
     ULONG value;
     INT i;
     BOOL Modified = FALSE;
-//    BOOL Domain = FALSE;
+#if 0
+    BOOL Domain = FALSE;
+#endif
     NET_API_STATUS Status;
     INT result = 0;
 
@@ -44,12 +46,13 @@ cmdAccounts(
             return 0;
         }
 
-/*
         if (_wcsicmp(argv[i], L"/domain") == 0)
         {
+            printf("The /DOMAIN option is not supported yet!\n");
+#if 0
             Domain = TRUE;
+#endif
         }
-*/
     }
 
     Status = NetUserModalsGet(NULL, 0, (LPBYTE*)&Info0);
diff --git a/base/applications/network/net/cmdLocalGroup.c b/base/applications/network/net/cmdLocalGroup.c
new file mode 100644 (file)
index 0000000..43400d1
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS net command
+ * FILE:
+ * PURPOSE:
+ *
+ * PROGRAMMERS:     Eric Kohl
+ */
+
+#include "net.h"
+
+
+static
+int
+CompareInfo(const void *a,
+            const void *b)
+{
+    return _wcsicmp(((PLOCALGROUP_INFO_0)a)->lgrpi0_name,
+                    ((PLOCALGROUP_INFO_0)b)->lgrpi0_name);
+}
+
+
+static
+NET_API_STATUS
+EnumerateLocalGroups(VOID)
+{
+    PLOCALGROUP_INFO_0 pBuffer = NULL;
+    PSERVER_INFO_100 pServer = NULL;
+    DWORD dwRead = 0, dwTotal = 0;
+    DWORD i;
+    DWORD_PTR ResumeHandle = 0;
+    NET_API_STATUS Status;
+
+
+    Status = NetServerGetInfo(NULL,
+                              100,
+                              (LPBYTE*)&pServer);
+    if (Status != NERR_Success)
+        return Status;
+
+    printf("\nAliases for \\\\%S\n\n", pServer->sv100_name);
+    printf("------------------------------------------\n");
+
+    NetApiBufferFree(pServer);
+
+    Status = NetLocalGroupEnum(NULL,
+                               0,
+                               (LPBYTE*)&pBuffer,
+                               MAX_PREFERRED_LENGTH,
+                               &dwRead,
+                               &dwTotal,
+                               &ResumeHandle);
+    if (Status != NERR_Success)
+        return Status;
+
+    qsort(pBuffer,
+          dwRead,
+          sizeof(PLOCALGROUP_INFO_0),
+          CompareInfo);
+
+//    printf("dwRead: %lu  dwTotal: %lu\n", dwRead, dwTotal);
+    for (i = 0; i < dwRead; i++)
+    {
+//        printf("%p\n", pBuffer[i].lgrpi0_name);
+         if (pBuffer[i].lgrpi0_name)
+            printf("*%S\n", pBuffer[i].lgrpi0_name);
+    }
+
+    NetApiBufferFree(pBuffer);
+
+    return NERR_Success;
+}
+
+
+INT
+cmdLocalGroup(
+    INT argc,
+    WCHAR **argv)
+{
+    INT i, j;
+    INT result = 0;
+    ULONG dwMemberCount = 0;
+    BOOL bAdd = FALSE;
+    BOOL bDelete = FALSE;
+#if 0
+    BOOL bDomain = FALSE;
+#endif
+    LPWSTR lpGroupName = NULL;
+    LPWSTR lpComment = NULL;
+    LPLOCALGROUP_MEMBERS_INFO_3 lpMembers = NULL;
+    LOCALGROUP_INFO_0 Info0;
+    LOCALGROUP_INFO_1 Info1;
+    LOCALGROUP_INFO_1002 Info1002;
+    NET_API_STATUS Status;
+
+    if (argc == 2)
+    {
+        Status = EnumerateLocalGroups();
+        printf("Status: %lu\n", Status);
+        return 0;
+    }
+
+    i = 2;
+    if (argv[i][0] != L'/')
+    {
+        lpGroupName = argv[i];
+        i++;
+    }
+
+    for (j = i; j < argc; j++)
+    {
+        if (argv[j][0] == L'/')
+            break;
+
+        dwMemberCount++;
+    }
+
+    printf("Member count: %lu\n", dwMemberCount);
+
+    if (dwMemberCount > 0)
+    {
+        lpMembers = RtlAllocateHeap(RtlGetProcessHeap(),
+                                    HEAP_ZERO_MEMORY,
+                                    dwMemberCount * sizeof(LPLOCALGROUP_MEMBERS_INFO_3));
+        if (lpMembers == NULL)
+            return 0;
+    }
+
+    j = 0;
+    for (; i < argc; i++)
+    {
+        if (argv[i][0] == L'/')
+            break;
+
+        lpMembers[j].lgrmi3_domainandname = argv[i];
+        j++;
+    }
+
+    for (; i < argc; i++)
+    {
+        if (_wcsicmp(argv[i], L"/help") == 0)
+        {
+            PrintResourceString(IDS_LOCALGROUP_HELP);
+            return 0;
+        }
+        else if (_wcsicmp(argv[i], L"/add") == 0)
+        {
+            bAdd = TRUE;
+        }
+        else if (_wcsicmp(argv[i], L"/delete") == 0)
+        {
+            bDelete = TRUE;
+        }
+        else if (_wcsnicmp(argv[i], L"/comment:", 9) == 0)
+        {
+            lpComment = &argv[i][9];
+        }
+        else if (_wcsicmp(argv[i], L"/domain") == 0)
+        {
+            printf("The /DOMAIN option is not supported yet!\n");
+#if 0
+            bDomain = TRUE;
+#endif
+        }
+        else
+        {
+            result = 1;
+            goto done;
+        }
+    }
+
+    if (lpGroupName == NULL)
+    {
+        result = 1;
+        goto done;
+    }
+
+    if (bAdd && bDelete)
+    {
+        result = 1;
+        goto done;
+    }
+
+#if 0
+    printf("Group:\n  %S\n", lpGroupName);
+
+    if (lpMembers != NULL)
+    {
+        printf("\nMembers:\n");
+        for (i = 0; i < dwMemberCount; i++)
+            printf("  %S\n", lpMembers[i].lgrmi3_domainandname);
+    }
+
+    if (lpComment != NULL)
+    {
+        printf("\nComment:\n  %S\n", lpComment);
+    }
+#endif
+
+    if (lpMembers == NULL)
+    {
+        if (!bAdd && !bDelete && lpComment != NULL)
+        {
+            /* Set group comment */
+            Info1002.lgrpi1002_comment = lpComment;
+            Status = NetLocalGroupSetInfo(NULL,
+                                          lpGroupName,
+                                          1002,
+                                          (LPBYTE)&Info1002,
+                                          NULL);
+            printf("Status: %lu\n", Status);
+        }
+        else if (bAdd && !bDelete)
+        {
+            /* Add the group */
+            if (lpComment == NULL)
+            {
+                Info0.lgrpi0_name = lpGroupName;
+            }
+            else
+            {
+                Info1.lgrpi1_name = lpGroupName;
+                Info1.lgrpi1_comment = lpComment;
+            }
+
+            Status = NetLocalGroupAdd(NULL,
+                             (lpComment == NULL) ? 0 : 1,
+                             (lpComment == NULL) ? (LPBYTE)&Info0 : (LPBYTE)&Info1,
+                             NULL);
+            printf("Status: %lu\n", Status);
+        }
+        else if (!bAdd && bDelete && lpComment == NULL)
+        {
+            /* Delete the group */
+            Status = NetLocalGroupDel(NULL,
+                                      lpGroupName);
+            printf("Status: %lu\n", Status);
+        }
+        else
+        {
+            result = 1;
+        }
+    }
+    else
+    {
+        if (bAdd && !bDelete && lpComment == NULL)
+        {
+            /* Add group members */
+            Status = NetLocalGroupAddMembers(NULL,
+                                    lpGroupName,
+                                    3,
+                                    (LPBYTE)lpMembers,
+                                    dwMemberCount);
+            printf("Status: %lu\n", Status);
+        }
+        else if (!bAdd && bDelete && lpComment == NULL)
+        {
+            /* Delete group members */
+            Status = NetLocalGroupDelMembers(NULL,
+                                    lpGroupName,
+                                    3,
+                                    (LPBYTE)lpMembers,
+                                    dwMemberCount);
+            printf("Status: %lu\n", Status);
+        }
+        else
+        {
+            result = 1;
+        }
+    }
+
+done:
+    if (lpMembers != NULL)
+        RtlFreeHeap(RtlGetProcessHeap(), 0, lpMembers);
+
+    if (result != 0)
+        PrintResourceString(IDS_LOCALGROUP_SYNTAX);
+
+    return result;
+}
+
+/* EOF */
index 3571f66..2d9083e 100644 (file)
@@ -18,7 +18,9 @@ BEGIN
     IDS_GROUP_HELP "GROUP\n..."
     IDS_HELPMSG_SYNTAX "Usage:\nNET HELPMSG <Error Code>"
     IDS_HELPMSG_HELP "HELPMSG\n..."
-    IDS_LOCALGROUP_SYNTAX "Usage:\nNET LOCALGROUP ..."
+    IDS_LOCALGROUP_SYNTAX "Usage:\nNET LOCALGROUP [groupname [/COMMENT:""text""]] [/DOMAIN]\n\
+               groupname {/ADD [/COMMENT:""text""] | /DELETE} [/DOMAIN]\n\
+               groupname name [...] {/ADD | /DELETE} [/DOMAIN]"
     IDS_LOCALGROUP_HELP "LOCALGROUP\n..."
     IDS_NAME_SYNTAX "Usage:\nNET NAME ..."
     IDS_NAME_HELP "NAME\n..."
index 56241fa..c8641eb 100644 (file)
@@ -24,7 +24,9 @@ BEGIN
     IDS_GROUP_HELP "GROUP\n..."
     IDS_HELPMSG_SYNTAX "Utilizare:\nNET HELPMSG <Error Code>"
     IDS_HELPMSG_HELP "HELPMSG\n..."
-    IDS_LOCALGROUP_SYNTAX "Utilizare:\nNET LOCALGROUP ..."
+    IDS_LOCALGROUP_SYNTAX "Utilizare:\nNET LOCALGROUP [groupname [/COMMENT:""text""]] [/DOMAIN]\n\
+               groupname {/ADD [/COMMENT:""text""] | /DELETE} [/DOMAIN]\n\
+               groupname name [...] {/ADD | /DELETE} [/DOMAIN]"
     IDS_LOCALGROUP_HELP "LOCALGROUP\n..."
     IDS_NAME_SYNTAX "Utilizare:\nNET NAME ..."
     IDS_NAME_HELP "NAME\n..."
index 29ec6f0..63531a8 100644 (file)
@@ -19,7 +19,9 @@ BEGIN
     IDS_GROUP_HELP "GROUP\n..."
     IDS_HELPMSG_SYNTAX "Использование:\nNET HELPMSG <Код ошибки>"
     IDS_HELPMSG_HELP "HELPMSG\n..."
-    IDS_LOCALGROUP_SYNTAX "Использование:\nNET LOCALGROUP ..."
+    IDS_LOCALGROUP_SYNTAX "Использование:\nNET LOCALGROUP [groupname [/COMMENT:""text""]] [/DOMAIN]\n\
+               groupname {/ADD [/COMMENT:""text""] | /DELETE} [/DOMAIN]\n\
+               groupname name [...] {/ADD | /DELETE} [/DOMAIN]"
     IDS_LOCALGROUP_HELP "LOCALGROUP\n..."
     IDS_NAME_SYNTAX "Использование:\nNET NAME ..."
     IDS_NAME_HELP "NAME\n..."
index f1560dd..9f226be 100644 (file)
@@ -28,7 +28,7 @@ COMMAND cmds[] =
     {L"group",      unimplemented},
     {L"help",       cmdHelp},
     {L"helpmsg",    cmdHelpMsg},
-    {L"localgroup", unimplemented},
+    {L"localgroup", cmdLocalGroup},
     {L"name",       unimplemented},
     {L"pause",      cmdPause},
     {L"print",      unimplemented},
index 93cf15d..016c018 100644 (file)
@@ -35,6 +35,7 @@ INT cmdAccounts(INT argc, WCHAR **argv);
 INT cmdContinue(INT argc, WCHAR **argv);
 INT cmdHelp(INT argc, WCHAR **argv);
 INT cmdHelpMsg(INT argc, WCHAR **argv);
+INT cmdLocalGroup(INT argc, WCHAR **argv);
 INT cmdPause(INT argc, WCHAR **argv);
 INT cmdStart(INT argc, WCHAR **argv);
 INT cmdStop(INT argc, WCHAR **argv);
index 961287b..093f783 100644 (file)
@@ -204,10 +204,13 @@ void UpdateColumnDataHints(void)
     HDITEM        hditem;
     WCHAR         text[260];
     ULONG         Index;
+    ULONG         uItems;
     WCHAR         szTemp[256];
-    unsigned int  i;
+    UINT          i;
+
+    uItems = min(SendMessageW(hProcessPageHeaderCtrl, HDM_GETITEMCOUNT, 0, 0), COLUMN_NMAX);
 
-    for (Index=0; Index<(ULONG)SendMessageW(hProcessPageHeaderCtrl, HDM_GETITEMCOUNT, 0, 0); Index++)
+    for (Index=0; Index<uItems; Index++)
     {
         memset(&hditem, 0, sizeof(HDITEM));
 
index d7f961c..71f8d67 100644 (file)
@@ -120,17 +120,15 @@ void GraphCtrl_Dispose(TGraphCtrl* this)
     if (this->m_brushBack     != NULL) DeleteObject(this->m_brushBack);
 }
 
-BOOL GraphCtrl_Create(TGraphCtrl* this, HWND hWnd, HWND hParentWnd, UINT nID)
+void GraphCtrl_Create(TGraphCtrl* this, HWND hWnd, HWND hParentWnd, UINT nID)
 {
-    BOOL result = 0;
-
     GraphCtrl_Init(this);
     this->m_hParentWnd = hParentWnd;
     this->m_hWnd = hWnd;
+
     GraphCtrl_Resize(this);
-    if (result != 0)
-        GraphCtrl_InvalidateCtrl(this, FALSE);
-    return result;
+
+    return;
 }
 
 void GraphCtrl_SetRange(TGraphCtrl* this, double dLower, double dUpper, int nDecimalPlaces)
index 3a5b838..e9ef84f 100644 (file)
@@ -88,7 +88,7 @@ extern WNDPROC OldGraphCtrlWndProc;
 double  GraphCtrl_AppendPoint(TGraphCtrl* this,
                               double dNewPoint0, double dNewPoint1,
                               double dNewPoint2, double dNewPoint3);
-BOOL    GraphCtrl_Create(TGraphCtrl* this, HWND hWnd, HWND hParentWnd,
+void    GraphCtrl_Create(TGraphCtrl* this, HWND hWnd, HWND hParentWnd,
 UINT nID);
 void    GraphCtrl_Dispose(TGraphCtrl* this);
 void    GraphCtrl_DrawPoint(TGraphCtrl* this);
index 36192dc..9e318b5 100644 (file)
@@ -152,15 +152,17 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
      */
 
     /* Get a token for this process.  */
-    if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
+    if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+    {
         /* Get the LUID for the debug privilege.  */
-        LookupPrivilegeValueW(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid);
-
-        tkp.PrivilegeCount = 1;  /* one privilege to set */
-        tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+        if (LookupPrivilegeValueW(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid))
+        {
+            tkp.PrivilegeCount = 1;  /* one privilege to set */
+            tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 
-        /* Get the debug privilege for this process. */
-        AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
+            /* Get the debug privilege for this process. */
+            AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
+        }
         CloseHandle(hToken);
     }
 
@@ -168,7 +170,8 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
     LoadSettings();
 
     /* Initialize perf data */
-    if (!PerfDataInitialize()) {
+    if (!PerfDataInitialize())
+    {
         return -1;
     }
 
index c5c127f..cc72cd8 100644 (file)
@@ -136,6 +136,7 @@ copy(TCHAR source[MAX_PATH],
         _tcscat(TempSrc,_T(".decrypt"));
         if (!CopyFileEx(source, TempSrc, NULL, NULL, FALSE, COPY_FILE_ALLOW_DECRYPTED_DESTINATION))
         {
+            CloseHandle (hFileSrc);
             nErrorLevel = 1;
             return 0;
         }
@@ -766,6 +767,7 @@ INT cmd_copy(LPTSTR param)
             /* Check Breaker */
             if (CheckCtrlBreak(BREAK_INPUT))
             {
+                FindClose(hFile);
                 freep(arg);
                 return 1;
             }
@@ -789,6 +791,7 @@ INT cmd_copy(LPTSTR param)
             if (_tcscmp(tmpDestPath, _T("\\\\.\\")) &&
                 !IsExistingDirectory(tmpDestPath))
             {
+                FindClose(hFile);
                 ConOutFormatMessage(GetLastError(), szSrcPath);
                 freep(arg);
                 nErrorLevel = 1;
index 925f2c3..14245d6 100644 (file)
@@ -382,7 +382,10 @@ BOOL DeleteFolder(LPTSTR FileName)
             {
                 SetFileAttributes(TempFileName,FILE_ATTRIBUTE_NORMAL);
                 if (!DeleteFile(TempFileName))
+                {
+                    FindClose (hFile);
                     return 0;
+                }
             }
 
         }while (FindNextFile (hFile, &f));
index 80e72bc..ca16fbd 100644 (file)
@@ -62,7 +62,7 @@ GetDateString(VOID)
     INT len;
     GetLocalTime(&t);
 
-    len = GetDateFormat(LOCALE_USER_DEFAULT, 0, &t, _T("ddd"), szDate, sizeof szDate);
+    len = GetDateFormat(LOCALE_USER_DEFAULT, 0, &t, _T("ddd"), szDate, sizeof(szDate) / sizeof(szDate[0]));
     szDate[len - 1] = _T(' ');
     FormatDate(&szDate[len], &t, TRUE);
     return szDate;
index f557f31..dd7dca9 100644 (file)
@@ -100,7 +100,7 @@ INT cmd_move (LPTSTR param)
     HANDLE hFile;
 
     /* used only when source and destination  directories are on different volume */
-    HANDLE hDestFile;
+    HANDLE hDestFile = NULL;
     WIN32_FIND_DATA findDestBuffer;
     TCHAR szMoveDest[MAX_PATH];
     TCHAR szMoveSrc[MAX_PATH];
@@ -505,6 +505,9 @@ INT cmd_move (LPTSTR param)
             FindNextFile (hFile, &findBuffer));
     FindClose (hFile);
 
+    if(hDestFile && hDestFile != INVALID_HANDLE_VALUE)
+        FindClose(hDestFile);
+
     freep (arg);
     return 0;
 }
index 864e3fb..9f19d74 100644 (file)
@@ -131,7 +131,10 @@ INT replace(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], DWORD dwFlags, BOOL *d
         else
             ConOutResPrintf(STRING_REPLACE_HELP10, dest);
         if ( !FilePromptYNA (0))
+        {
+            CloseHandle (hFileSrc);
             return 0;
+        }
     }
 
     /* Output depending on add flag */
@@ -220,7 +223,7 @@ INT recReplace(DWORD dwFlags,
     HANDLE hFile;
     WIN32_FIND_DATA findBuffer;
 
-    /* Get file handel to the sourcefile(s) */
+    /* Get file handle to the sourcefile(s) */
     hFile = FindFirstFile (szSrcPath, &findBuffer);
 
     /*
@@ -302,6 +305,8 @@ INT recReplace(DWORD dwFlags,
     /* Take next sourcefile if any */
     } while(FindNextFile (hFile, &findBuffer));
 
+    FindClose(hFile);
+
     return filesReplaced;
 }
 
@@ -378,6 +383,8 @@ INT recFindSubDirs(DWORD dwFlags,
         /* Get the next handle */
     } while(FindNextFile (hFile, &findBuffer));
 
+    FindClose(hFile);
+
     return filesReplaced;
 }
 
index 060fb05..6e1c294 100644 (file)
@@ -110,7 +110,7 @@ public:
                                UINT cFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
 
                                for(UINT i=0; i<cFiles; ++i) {
-                                       DragQueryFile(hDrop, i, szFileName, sizeof(szFileName));
+                                       DragQueryFile(hDrop, i, szFileName, sizeof(szFileName) / sizeof(szFileName[0]));
 
                                        if (DROPEFFECT_COPY & *pdwEffect) {
                                                 // copy the file or dir
index 628255f..28ae13e 100644 (file)
@@ -448,7 +448,6 @@ int WINAPI _tWinMain(
                                                        nRetValue = EXITCODE_FAILURE;
                                        }
                                        else {
-                                               FreeLibrary(hDll);
                                                // DllInstall was not found, display an error message
                                                lptMsgBuffer = (LPTSTR)malloc((_tcslen(MissingEntry) - 8 + _tcslen(tszDllInstall) * 2 + _tcslen(lptDllName) * 2 + 1) * sizeof(TCHAR));
                                                _stprintf(lptMsgBuffer,MissingEntry,lptDllName,tszDllInstall,tszDllInstall,lptDllName);
index bdc66fd..78e6360 100755 (executable)
@@ -77,6 +77,7 @@ if defined ROS_ARCH (
                 set CMAKE_GENERATOR="Visual Studio 11 Win64"\r
             ) else if "!ARCH!" == "arm" (\r
                 set CMAKE_GENERATOR="Visual Studio 11 ARM"\r
+                set CMAKE_GENERATOR_HOST="Visual Studio 11"\r
             ) else (\r
                 set CMAKE_GENERATOR="Visual Studio 11"\r
             )\r
@@ -85,6 +86,7 @@ if defined ROS_ARCH (
                 set CMAKE_GENERATOR="Visual Studio 12 Win64"\r
             ) else if "!ARCH!" == "arm" (\r
                 set CMAKE_GENERATOR="Visual Studio 12 ARM"\r
+                set CMAKE_GENERATOR_HOST="Visual Studio 12"\r
             ) else (\r
                 set CMAKE_GENERATOR="Visual Studio 12"\r
             )\r
@@ -116,6 +118,9 @@ if %USE_VSCMD% == 1 (
     ) else (\r
         set CMAKE_GENERATOR="Ninja"\r
     )\r
+    if "!ARCH!" == "arm" (\r
+        set CMAKE_GENERATOR_HOST=!CMAKE_GENERATOR!\r
+    )\r
 )\r
 \r
 :: Create directories\r
@@ -146,7 +151,7 @@ set REACTOS_BUILD_TOOLS_DIR=%CD%
 :: Use x86 for ARM host tools\r
 if "%ARCH%" == "arm" (\r
     :: Launch new script instance for x86 host tools configuration\r
-    start "Preparing host tools for ARM cross build..." /I /B /WAIT %~dp0configure.cmd arm_hosttools "%VSINSTALLDIR%VC\vcvarsall.bat" %CMAKE_GENERATOR%\r
+    start "Preparing host tools for ARM cross build..." /I /B /WAIT %~dp0configure.cmd arm_hosttools "%VSINSTALLDIR%VC\vcvarsall.bat" %CMAKE_GENERATOR_HOST%\r
 ) else (\r
     cmake -G %CMAKE_GENERATOR% -DARCH:STRING=%ARCH% "%REACTOS_SOURCE_DIR%"\r
 )\r
index 9190fd8..3f93126 100644 (file)
@@ -102,6 +102,10 @@ foreach(_keyboard_layout ${_keyboard_layouts})
         add_target_link_flags(${_keyboard_layout} "-Wl,-T,${CMAKE_SOURCE_DIR}/kbdlayout.lds")
     endif()
 
+    if (STACK_PROTECTOR)
+        target_link_libraries(${_keyboard_layout} gcc_ssp)
+    endif()
+
     if(RUNTIME_CHECKS)
         target_link_libraries(${_keyboard_layout} runtmchk)
     endif()
index 6265f50..9d684db 100644 (file)
@@ -586,7 +586,6 @@ DeviceProblemTextW(IN HMACHINE hMachine  OPTIONAL,
                                             &szProblem,
                                             szInfo,
                                             uProblemId);
-            LocalFree((HLOCAL)szInfo);
         }
         else
         {
index e3c87c1..699c006 100644 (file)
@@ -6,6 +6,7 @@
  * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
  *                  Gerhard W. Gruber (sparhawk_at_gmx.at)
  *                  Dmitry Philippov (shedon@mail.ru)
+ *                  Pierre Schweitzer (pierre@reactos.org)
  * UPDATE HISTORY:
  *                  Created 01/11/98
  *                  DP (29/07/2006)
 
 #include <k32.h>
 #include <malloc.h>
+#include <strsafe.h>
 #define NDEBUG
 #include <debug.h>
 DEBUG_CHANNEL(kernel32file);
 
 /* GLOBALS *****************************************************************/
 
-/* FUNCTIONS ****************************************************************/
-static BOOL
-RemoveReadOnlyAttributeW(IN LPCWSTR lpFileName)
+/* DEFINES *****************************************************************/
+typedef struct _COPY_PROGRESS_CONTEXT
 {
-    DWORD Attributes;
-    Attributes = GetFileAttributesW(lpFileName);
-    if (Attributes != INVALID_FILE_ATTRIBUTES)
-    {  
-        return SetFileAttributesW(lpFileName,Attributes - 
-                                             (Attributes & ~FILE_ATTRIBUTE_READONLY));
-    }
-    return FALSE;
-}
-
+    ULONG Flags;
+    LPPROGRESS_ROUTINE UserRoutine;
+    LPVOID UserData;
+} COPY_PROGRESS_CONTEXT, *PCOPY_PROGRESS_CONTEXT;
 
-/***********************************************************************
- *           add_boot_rename_entry
- *
- * Adds an entry to the registry that is loaded when windows boots and
- * checks if there are some files to be removed or renamed/moved.
- * <fn1> has to be valid and <fn2> may be NULL. If both pointers are
- * non-NULL then the file is moved, otherwise it is deleted.  The
- * entry of the registrykey is always appended with two zero
- * terminated strings. If <fn2> is NULL then the second entry is
- * simply a single 0-byte. Otherwise the second filename goes
- * there. The entries are prepended with \??\ before the path and the
- * second filename gets also a '!' as the first character if
- * MOVEFILE_REPLACE_EXISTING is set. After the final string another
- * 0-byte follows to indicate the end of the strings.
- * i.e.:
- * \??\D:\test\file1[0]
- * !\??\D:\test\file1_renamed[0]
- * \??\D:\Test|delete[0]
- * [0]                        <- file is to be deleted, second string empty
- * \??\D:\test\file2[0]
- * !\??\D:\test\file2_renamed[0]
- * [0]                        <- indicates end of strings
- *
- * or:
- * \??\D:\test\file1[0]
- * !\??\D:\test\file1_renamed[0]
- * \??\D:\Test|delete[0]
- * [0]                        <- file is to be deleted, second string empty
- * [0]                        <- indicates end of strings
- *
+/* FUNCTIONS ****************************************************************/
+/*
+ * @implemented
  */
-static BOOL add_boot_rename_entry( LPCWSTR source, LPCWSTR dest, DWORD flags )
+NTSTATUS
+WINAPI
+BasepMoveFileDelayed(IN PUNICODE_STRING ExistingPath,
+                     IN PUNICODE_STRING NewPath,
+                     IN INT KeyId,
+                     IN BOOL CreateIfNotFound)
 {
-    static const WCHAR ValueName[] = {'P','e','n','d','i','n','g',
-                                      'F','i','l','e','R','e','n','a','m','e',
-                                      'O','p','e','r','a','t','i','o','n','s',0};
-
-    UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Session Manager");
-
-    static const int info_size = FIELD_OFFSET( KEY_VALUE_PARTIAL_INFORMATION, Data );
-
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    UNICODE_STRING nameW, source_name, dest_name;
-    KEY_VALUE_PARTIAL_INFORMATION *info;
-    BOOL rc = FALSE;
-    HANDLE Reboot = NULL;
-    DWORD len1, len2;
-    DWORD DestLen = 0;
-    DWORD DataSize = 0;
-    BYTE *Buffer = NULL;
-    WCHAR *p;
+#define STRING_LENGTH 0x400
     NTSTATUS Status;
+    HANDLE KeyHandle;
+    PVOID Buffer, BufferBegin;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    PWSTR PendingOperations, BufferWrite;
+    ULONG DataSize, BufferLength, StringLength = STRING_LENGTH;
+    UNICODE_STRING SessionManagerString, PendingOperationsString;
+    /* +6 because a INT shouldn't take more than 6 chars. Especially given the call path */
+    WCHAR PendingOperationsBuffer[sizeof(L"PendingFileRenameOperations") / sizeof(WCHAR) + 6];
 
-    TRACE("add_boot_rename_entry( %S, %S, %lu ) \n", source, dest, flags);
-
-    if(dest)
-        DestLen = wcslen(dest);
+    RtlInitUnicodeString(&SessionManagerString, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager");
 
-    if (!RtlDosPathNameToNtPathName_U( source, &source_name, NULL, NULL ))
+    /* Select appropriate key for adding our file */
+    if (KeyId == 1)
     {
-        SetLastError( ERROR_PATH_NOT_FOUND );
-        return FALSE;
+        PendingOperations = L"PendingFileRenameOperations";
     }
-    dest_name.Buffer = NULL;
-    if (DestLen && !RtlDosPathNameToNtPathName_U( dest, &dest_name, NULL, NULL ))
+    else
     {
-        RtlFreeHeap( RtlGetProcessHeap(), 0, source_name.Buffer );
-        SetLastError( ERROR_PATH_NOT_FOUND );
-        return FALSE;
+        StringCbPrintfW(PendingOperationsBuffer, sizeof(PendingOperationsBuffer), L"PendingFileRenameOperations%d", KeyId);
+        PendingOperations = PendingOperationsBuffer;
     }
+    RtlInitUnicodeString(&PendingOperationsString, PendingOperations);
 
     InitializeObjectAttributes(&ObjectAttributes,
-                               &KeyName,
+                               &SessionManagerString,
                                OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
-                               NULL,
-                               NULL);
-
-     Status = NtCreateKey(&Reboot, 
-                          KEY_QUERY_VALUE | KEY_SET_VALUE,
-                          &ObjectAttributes,
-                          0,
-                          NULL,
-                          REG_OPTION_NON_VOLATILE,
-                          NULL);
-
-     if (Status == STATUS_ACCESS_DENIED)
-     {
-         Status = NtCreateKey(
-             &Reboot, 
-             KEY_QUERY_VALUE | KEY_SET_VALUE,
-             &ObjectAttributes,
-             0,
-             NULL,
-             REG_OPTION_BACKUP_RESTORE,
-             NULL);
-     }
+                               NULL, NULL);
+
+    /* Open parent key */
+    Status = NtCreateKey(&KeyHandle,
+                         GENERIC_READ | GENERIC_WRITE,
+                         &ObjectAttributes, 0, NULL,
+                         REG_OPTION_NON_VOLATILE, NULL);
+    if (Status == STATUS_ACCESS_DENIED)
+    {
+        Status = NtCreateKey(&KeyHandle,
+                             GENERIC_READ | GENERIC_WRITE,
+                             &ObjectAttributes, 0, NULL,
+                             REG_OPTION_BACKUP_RESTORE, NULL);
+    }
 
     if (!NT_SUCCESS(Status))
     {
-        WARN("NtCreateKey() failed (Status 0x%lx)\n", Status);
-        if (source_name.Buffer)
-            RtlFreeHeap(RtlGetProcessHeap(), 0, source_name.Buffer);
-        if (dest_name.Buffer)
-            RtlFreeHeap(RtlGetProcessHeap(), 0, dest_name.Buffer);
-        return FALSE;
+        return Status;
     }
 
-    len1 = source_name.Length + sizeof(WCHAR);
-    if (DestLen)
+    /* Reserve enough to read previous string + to append our with required null chars */
+    BufferLength = NewPath->Length + ExistingPath->Length + STRING_LENGTH + 3 * sizeof(WCHAR);
+    /* Check we didn't overflow */
+    if (BufferLength < STRING_LENGTH)
     {
-        len2 = dest_name.Length + sizeof(WCHAR);
-        if (flags & MOVEFILE_REPLACE_EXISTING)
-            len2 += sizeof(WCHAR); /* Plus 1 because of the leading '!' */
+        NtClose(KeyHandle);
+        return STATUS_BUFFER_TOO_SMALL;
     }
-    else
+
+    while (TRUE)
     {
-        len2 = sizeof(WCHAR); /* minimum is the 0 characters for the empty second string */
+        /* Allocate output buffer */
+        Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
+        if (Buffer == NULL)
+        {
+            NtClose(KeyHandle);
+            return STATUS_NO_MEMORY;
+        }
+
+        Status = NtQueryValueKey(KeyHandle,
+                                 &PendingOperationsString,
+                                 KeyValuePartialInformation,
+                                 Buffer, StringLength, &DataSize);
+        if (Status != STATUS_BUFFER_OVERFLOW)
+        {
+            break;
+        }
+
+        /* If buffer was too small, then, reallocate one which is big enough */
+        StringLength = DataSize;
+        RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
+        BufferLength = ExistingPath->Length + StringLength + NewPath->Length + 3 * sizeof(WCHAR);
+        if (BufferLength < StringLength)
+        {
+            NtClose(KeyHandle);
+            return STATUS_BUFFER_TOO_SMALL;
+        }
     }
 
-    RtlInitUnicodeString( &nameW, ValueName );
-
-    /* First we check if the key exists and if so how many bytes it already contains. */
-    Status = NtQueryValueKey(
-        Reboot,
-        &nameW,
-        KeyValuePartialInformation,
-        NULL,
-        0, 
-        &DataSize );
-    if ((Status == STATUS_BUFFER_OVERFLOW) ||
-        (Status == STATUS_BUFFER_TOO_SMALL))
+    /* Check if it existed - if not, create only IF asked to */
+    if (!NT_SUCCESS(Status) && (Status != STATUS_OBJECT_NAME_NOT_FOUND || !CreateIfNotFound))
     {
-        if (!(Buffer = HeapAlloc(GetProcessHeap(), 0, DataSize + len1 + len2 + sizeof(WCHAR))))
-            goto Quit;
-        Status = NtQueryValueKey(Reboot, &nameW, KeyValuePartialInformation,
-            Buffer, DataSize, &DataSize);
-        if(!NT_SUCCESS(Status))
-            goto Quit;
-        info = (KEY_VALUE_PARTIAL_INFORMATION *)Buffer;
-        if (info->Type != REG_MULTI_SZ) goto Quit;
-        if (DataSize > sizeof(info)) DataSize -= sizeof(WCHAR);  /* remove terminating null (will be added back later) */
+        NtClose(KeyHandle);
+        RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
+        return Status;
+    }
+
+    if (!NT_SUCCESS(Status))
+    {
+        /* We didn't find any - ie, we create, so use complete buffer */
+        BufferBegin = Buffer;
+        BufferWrite = Buffer;
     }
     else
     {
-        DataSize = info_size;
-        if (!(Buffer = HeapAlloc( GetProcessHeap(), 0, DataSize + len1 + len2 + sizeof(WCHAR) )))
-            goto Quit;
+        PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)Buffer;
+
+        /* Get data, our buffer begin and then where we should append data (+ null char) */
+        BufferBegin = PartialInfo->Data;
+        BufferWrite = (PWSTR)((ULONG_PTR)PartialInfo->Data + PartialInfo->DataLength + sizeof(WCHAR));
     }
 
-    memcpy( Buffer + DataSize, source_name.Buffer, len1 );
-    DataSize += len1;
-    p = (WCHAR *)(Buffer + DataSize);
-    if (DestLen)
+    /* First copy existing */
+    RtlCopyMemory(BufferWrite, ExistingPath->Buffer, ExistingPath->Length);
+    BufferWrite += ExistingPath->Length / sizeof(WCHAR);
+    /* And append null char */
+    *BufferWrite = UNICODE_NULL;
+    ++BufferWrite;
+    /* Append destination */
+    RtlCopyMemory(BufferWrite, NewPath->Buffer, NewPath->Length);
+    BufferWrite += NewPath->Length / sizeof(WCHAR);
+    /* And append two null char (end of string) */
+    *BufferWrite = UNICODE_NULL;
+    ++BufferWrite;
+    *BufferWrite = UNICODE_NULL;
+
+    /* Set new value */
+    Status = NtSetValueKey(KeyHandle,
+                           &PendingOperationsString,
+                           0, REG_MULTI_SZ, BufferBegin,
+                           (ULONG_PTR)BufferWrite - (ULONG_PTR)BufferBegin + sizeof(WCHAR));
+
+    NtClose(KeyHandle);
+    RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
+
+    return Status;
+}
+
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+WINAPI
+BasepNotifyTrackingService(IN PHANDLE ExistingHandle,
+                           IN POBJECT_ATTRIBUTES ObjectAttributes,
+                           IN HANDLE NewHandle,
+                           IN PUNICODE_STRING NewPath)
+{
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
+BasepMoveFileCopyProgress(IN LARGE_INTEGER TotalFileSize,
+                          IN LARGE_INTEGER TotalBytesTransferred,
+                          IN LARGE_INTEGER StreamSize,
+                          IN LARGE_INTEGER StreamBytesTransferred,
+                          IN DWORD dwStreamNumber,
+                          IN DWORD dwCallbackReason,
+                          IN HANDLE hSourceFile,
+                          IN HANDLE hDestinationFile,
+                          IN LPVOID lpData OPTIONAL)
+{
+    DWORD Ret = 0;
+    PCOPY_PROGRESS_CONTEXT Context = (PCOPY_PROGRESS_CONTEXT)lpData;
+
+    if (Context->Flags & MOVEFILE_WRITE_THROUGH)
     {
-        if (flags & MOVEFILE_REPLACE_EXISTING)
-            *p++ = '!';
-        memcpy( p, dest_name.Buffer, len2 );
-        DataSize += len2;
+        if (!dwCallbackReason)
+        {
+            if (StreamBytesTransferred.QuadPart == StreamSize.QuadPart)
+            {
+                FlushFileBuffers(hDestinationFile);
+            }
+        }
     }
-    else
+
+    if (Context->UserRoutine)
     {
-        *p = 0;
-        DataSize += sizeof(WCHAR);
+        Ret = Context->UserRoutine(TotalFileSize,
+                                   TotalBytesTransferred,
+                                   StreamSize,
+                                   StreamBytesTransferred,
+                                   dwStreamNumber,
+                                   dwCallbackReason,
+                                   hSourceFile,
+                                   hDestinationFile,
+                                   Context->UserData);
     }
 
-    /* add final null */
-    p = (WCHAR *)(Buffer + DataSize);
-    *p = 0;
-    DataSize += sizeof(WCHAR);
-
-    rc = NT_SUCCESS(NtSetValueKey(Reboot, &nameW, 0, REG_MULTI_SZ, Buffer + info_size, DataSize - info_size));
-
- Quit:
-    RtlFreeHeap(RtlGetProcessHeap(), 0, source_name.Buffer);
-    if (dest_name.Buffer)
-        RtlFreeHeap(RtlGetProcessHeap(), 0, dest_name.Buffer);
-    NtClose(Reboot);
-    if(Buffer)
-        HeapFree(GetProcessHeap(), 0, Buffer);
-    return(rc);
+    return Ret;
 }
 
 
@@ -226,465 +245,329 @@ static BOOL add_boot_rename_entry( LPCWSTR source, LPCWSTR dest, DWORD flags )
  */
 BOOL
 WINAPI
-MoveFileWithProgressW (
-       LPCWSTR                 lpExistingFileName,
-       LPCWSTR                 lpNewFileName,
-       LPPROGRESS_ROUTINE      lpProgressRoutine,
-       LPVOID                  lpData,
-       DWORD                   dwFlags
-       )
+MoveFileWithProgressW(IN LPCWSTR lpExistingFileName,
+                      IN LPCWSTR lpNewFileName,
+                      IN LPPROGRESS_ROUTINE lpProgressRoutine,
+                      IN LPVOID lpData,
+                      IN DWORD dwFlags)
 {
-       HANDLE hFile = NULL, hNewFile = NULL;
-       IO_STATUS_BLOCK IoStatusBlock;
+    NTSTATUS Status;
+    PWSTR NewBuffer;
+    IO_STATUS_BLOCK IoStatusBlock;
+    COPY_PROGRESS_CONTEXT CopyContext;
     OBJECT_ATTRIBUTES ObjectAttributes;
-       PFILE_RENAME_INFORMATION FileRename;
-       NTSTATUS errCode;
-       BOOL Result;
-       UNICODE_STRING DstPathU;
-       BOOL folder = FALSE;
+    PFILE_RENAME_INFORMATION RenameInfo;
+    UNICODE_STRING NewPathU, ExistingPathU;
+    FILE_ATTRIBUTE_TAG_INFORMATION FileAttrTagInfo;
+    HANDLE SourceHandle = INVALID_HANDLE_VALUE, NewHandle, ExistingHandle;
+    BOOL Ret = FALSE, ReplaceIfExists, DelayUntilReboot, AttemptReopenWithoutReparse;
 
-       TRACE("MoveFileWithProgressW()\n");
+    DPRINT("MoveFileWithProgressW(%S, %S, %p, %p, %x)\n", lpExistingFileName, lpNewFileName, lpProgressRoutine, lpData, dwFlags);
 
-       if (dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT)
-               return add_boot_rename_entry( lpExistingFileName, lpNewFileName, dwFlags );
+    NewPathU.Buffer = NULL;
+    ExistingPathU.Buffer = NULL;
 
-//    if (dwFlags & MOVEFILE_WRITE_THROUGH)
-//        FIXME("MOVEFILE_WRITE_THROUGH unimplemented\n");
+    _SEH2_TRY
+    {
+        /* Don't allow renaming to a disk */
+        if (lpNewFileName && RtlIsDosDeviceName_U(lpNewFileName))
+        {
+            BaseSetLastNTError(STATUS_OBJECT_NAME_COLLISION);
+            _SEH2_LEAVE;
+        }
 
-    if (!lpNewFileName)
-        return DeleteFileW(lpExistingFileName);
+        ReplaceIfExists = !!(dwFlags & MOVEFILE_REPLACE_EXISTING);
 
-    /* validate & translate the filename */
-    if (!RtlDosPathNameToNtPathName_U (lpNewFileName,
-                                          &DstPathU,
-                                          NULL,
-                                          NULL))
-    {
-        WARN("Invalid destination path\n");
-        SetLastError(ERROR_PATH_NOT_FOUND);
-        return FALSE;
-    }
+        /* Get file path */
+        if (!RtlDosPathNameToNtPathName_U(lpExistingFileName, &ExistingPathU, NULL, NULL))
+        {
+            BaseSetLastNTError(STATUS_OBJECT_PATH_NOT_FOUND);
+            _SEH2_LEAVE;
+        }
 
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &DstPathU,
-                               OBJ_CASE_INSENSITIVE,
+        /* Sanitize input */
+        DelayUntilReboot = !!(dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT);
+        if (DelayUntilReboot && (dwFlags & MOVEFILE_CREATE_HARDLINK))
+        {
+            BaseSetLastNTError(STATUS_INVALID_PARAMETER);
+            _SEH2_LEAVE;
+        }
+
+        /* Unless we manage a proper opening, we'll attempt to reopen without reparse support */
+        AttemptReopenWithoutReparse = TRUE;
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &ExistingPathU,
+                                   OBJ_CASE_INSENSITIVE,
+                                   NULL,
+                                   NULL);
+        /* Attempt to open source file */
+        Status = NtOpenFile(&SourceHandle,
+                            FILE_READ_ATTRIBUTES | DELETE | SYNCHRONIZE, 
+                            &ObjectAttributes,
+                            &IoStatusBlock,
+                            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                            FILE_OPEN_FOR_BACKUP_INTENT | ((dwFlags & MOVEFILE_WRITE_THROUGH) ? FILE_WRITE_THROUGH : 0));
+        if (!NT_SUCCESS(Status))
+        {
+            /* If we failed and the file doesn't exist, don't attempt to reopen without reparse */
+            if (DelayUntilReboot &&
+                (Status == STATUS_SHARING_VIOLATION || Status == STATUS_OBJECT_NAME_NOT_FOUND || Status == STATUS_OBJECT_PATH_NOT_FOUND))
+            {
+                /* Here we don't fail completely, as we postpone the operation to reboot
+                 * File might exist afterwards, and we don't need a handle here
+                 */
+                SourceHandle = INVALID_HANDLE_VALUE;
+                AttemptReopenWithoutReparse = FALSE;
+            }
+            /* If we failed for any reason than unsupported reparse, fail completely */
+            else if (Status != STATUS_INVALID_PARAMETER)
+            {
+                BaseSetLastNTError(Status);
+                _SEH2_LEAVE;
+            }
+        }
+        else
+        {
+            /* We managed to open, so query information */
+            Status = NtQueryInformationFile(SourceHandle,
+                                            &IoStatusBlock,
+                                            &FileAttrTagInfo,
+                                            sizeof(FILE_ATTRIBUTE_TAG_INFORMATION),
+                                            FileAttributeTagInformation);
+            if (!NT_SUCCESS(Status))
+            {
+                /* Do not tolerate any other error than something related to not supported operation */
+                if (Status != STATUS_NOT_IMPLEMENTED && Status != STATUS_INVALID_PARAMETER)
+                {
+                    BaseSetLastNTError(Status);
+                    _SEH2_LEAVE;
+                }
+
+                /* Not a reparse point, no need to reopen, it's fine */
+                AttemptReopenWithoutReparse = FALSE;
+            }
+            /* Validate the reparse point (do we support it?) */
+            else if (FileAttrTagInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT &&
+                     FileAttrTagInfo.ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
+            {
+                NtClose(SourceHandle);
+                SourceHandle = INVALID_HANDLE_VALUE;
+            }
+        }
+
+        /* Simply reopen if required */
+        if (AttemptReopenWithoutReparse)
+        {
+            Status = NtOpenFile(&SourceHandle,
+                                DELETE | SYNCHRONIZE,
+                                &ObjectAttributes,
+                                &IoStatusBlock,
+                                FILE_SHARE_READ | FILE_SHARE_WRITE,
+                                ((dwFlags & MOVEFILE_WRITE_THROUGH) ? FILE_WRITE_THROUGH : 0));
+            if (!NT_SUCCESS(Status))
+            {
+                BaseSetLastNTError(Status);
+                _SEH2_LEAVE;
+            }
+        }
+
+        /* Nullify string if we're to use it */
+        if (DelayUntilReboot && !lpNewFileName)
+        {
+            RtlInitUnicodeString(&NewPathU, 0);
+        }
+        /* Check whether path exists */
+        else if (!RtlDosPathNameToNtPathName_U(lpNewFileName, &NewPathU, 0, 0))
+        {
+            BaseSetLastNTError(STATUS_OBJECT_PATH_NOT_FOUND);
+            _SEH2_LEAVE;
+        }
+
+        /* Handle postponed renaming */
+        if (DelayUntilReboot)
+        {
+            /* If new file exists and we're allowed to replace, then mark the path with ! */
+            if (ReplaceIfExists && NewPathU.Length)
+            {
+                NewBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, NewPathU.Length + sizeof(WCHAR));
+                if (NewBuffer == NULL)
+                {
+                    BaseSetLastNTError(STATUS_NO_MEMORY);
+                    _SEH2_LEAVE;
+                }
+
+                NewBuffer[0] = L'!';
+                RtlCopyMemory(&NewBuffer[1], NewPathU.Buffer, NewPathU.Length);
+                NewPathU.Length += sizeof(WCHAR);
+                NewPathU.MaximumLength += sizeof(WCHAR);
+                RtlFreeHeap(RtlGetProcessHeap(), 0, NewPathU.Buffer);
+                NewPathU.Buffer = NewBuffer;
+            }
+
+            /* Check whether 'copy' renaming is allowed if required */
+            if (RtlDetermineDosPathNameType_U(lpExistingFileName) == RtlPathTypeUncAbsolute || dwFlags & MOVEFILE_COPY_ALLOWED)
+            {
+                Status = STATUS_INVALID_PARAMETER;
+            }
+            else
+            {
+                /* First, probe 2nd key to see whether it exists - if so, it will be appended there */
+                Status = BasepMoveFileDelayed(&ExistingPathU, &NewPathU, 2, FALSE);
+                if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+                {
+                    /* If doesn't exist, append to first key first, creating it if it doesn't exist */
+                    Status = BasepMoveFileDelayed(&ExistingPathU, &NewPathU, 1, TRUE);
+
+                    if (Status == STATUS_INSUFFICIENT_RESOURCES)
+                    {
+                        /* If it failed because it's too big, then create 2nd key and put it there */
+                        Status = BasepMoveFileDelayed(&ExistingPathU, &NewPathU, 2, TRUE);
+                    }
+                }
+            }
+
+            /* If we failed at some point, return the error */
+            if (!NT_SUCCESS(Status))
+            {
+                BaseSetLastNTError(Status);
+                _SEH2_LEAVE;
+            }
+
+            Ret = TRUE;
+            _SEH2_LEAVE;
+        }
+
+        /* At that point, we MUST have a source handle */
+        ASSERT(SourceHandle != INVALID_HANDLE_VALUE);
+
+        /* Allocate renaming buffer and fill it */
+        RenameInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, NewPathU.Length + sizeof(FILE_RENAME_INFORMATION));
+        if (RenameInfo == NULL)
+        {
+            BaseSetLastNTError(STATUS_NO_MEMORY);
+            _SEH2_LEAVE;
+        }
+
+        RtlCopyMemory(&RenameInfo->FileName, NewPathU.Buffer, NewPathU.Length);
+        RenameInfo->ReplaceIfExists = ReplaceIfExists;
+        RenameInfo->RootDirectory = 0;
+        RenameInfo->FileNameLength = NewPathU.Length;
+
+        /* Attempt to rename the file */
+        Status = NtSetInformationFile(SourceHandle,
+                                      &IoStatusBlock,
+                                      RenameInfo,
+                                      NewPathU.Length + sizeof(FILE_RENAME_INFORMATION),
+                                      ((dwFlags & MOVEFILE_CREATE_HARDLINK) ? FileLinkInformation : FileRenameInformation));
+        RtlFreeHeap(RtlGetProcessHeap(), 0, RenameInfo);
+        if (NT_SUCCESS(Status))
+        {
+            /* If it succeed, all fine, quit */
+            Ret = TRUE;
+            _SEH2_LEAVE;
+        }
+        /* If we failed for any other reason than not the same device, fail
+         * If we failed because of different devices, only allow renaming if user allowed copy
+         */
+        if (Status != STATUS_NOT_SAME_DEVICE || !(dwFlags & MOVEFILE_COPY_ALLOWED))
+        {
+            /* ReactOS hack! To be removed once all FSD have proper renaming support
+             * Just leave status to error and leave 
+             */
+            if (Status == STATUS_NOT_IMPLEMENTED)
+            {
+                DPRINT1("Forcing copy, renaming not supported by FSD\n");
+            }
+            else
+            {
+                BaseSetLastNTError(Status);
+                _SEH2_LEAVE;
+            }
+        }
+
+        /* Close source file */
+        NtClose(SourceHandle);
+        SourceHandle = INVALID_HANDLE_VALUE;
+
+        /* Issue the copy of the file */
+        CopyContext.Flags = dwFlags;
+        CopyContext.UserRoutine = lpProgressRoutine;
+        CopyContext.UserData = lpData;
+        NewHandle = INVALID_HANDLE_VALUE;
+        ExistingHandle = INVALID_HANDLE_VALUE;
+
+        Ret = BasepCopyFileExW(lpExistingFileName,
+                               lpNewFileName,
+                               BasepMoveFileCopyProgress,
+                               &CopyContext,
                                NULL,
-                               NULL);
+                               (ReplaceIfExists == 0) | COPY_FILE_OPEN_SOURCE_FOR_WRITE,
+                               0,
+                               &ExistingHandle,
+                               &NewHandle);
+        if (!Ret)
+        {
+            /* If it failed, don't leak any handle */
+            if (ExistingHandle != INVALID_HANDLE_VALUE)
+            {
+                CloseHandle(ExistingHandle);
+                ExistingHandle = INVALID_HANDLE_VALUE;
+            }
+        }
+        else if (ExistingHandle != INVALID_HANDLE_VALUE)
+        {
+            if (NewHandle != INVALID_HANDLE_VALUE)
+            {
+                /* If copying succeed, notify */
+                Status = BasepNotifyTrackingService(&ExistingHandle, &ObjectAttributes, NewHandle, &NewPathU);
+                if (!NT_SUCCESS(Status))
+                {
+                    /* Fail in case it had to succeed */
+                    if (dwFlags & MOVEFILE_FAIL_IF_NOT_TRACKABLE)
+                    {
+                        if (NewHandle != INVALID_HANDLE_VALUE)
+                            CloseHandle(NewHandle);
+                        NewHandle = INVALID_HANDLE_VALUE;
+                        DeleteFileW(lpNewFileName);
+                        Ret = FALSE;
+                        BaseSetLastNTError(Status);
+                    }
+                }
+            }
 
-    errCode = NtOpenFile( &hNewFile,
-                          GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
-                          &ObjectAttributes,
-                          &IoStatusBlock,
-                          0,
-                          FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
-                          ((dwFlags & MOVEFILE_WRITE_THROUGH) ? FILE_WRITE_THROUGH : 0) );
+            CloseHandle(ExistingHandle);
+            ExistingHandle = INVALID_HANDLE_VALUE;
+        }
 
-    if (NT_SUCCESS(errCode)) /* Destination exists */
-    {
-        NtClose(hNewFile);
+        /* In case copy worked, close file */
+        if (NewHandle != INVALID_HANDLE_VALUE)
+        {
+            CloseHandle(NewHandle);
+            NewHandle = INVALID_HANDLE_VALUE;
+        }
 
-        if (!(dwFlags & MOVEFILE_REPLACE_EXISTING))
+        /* If it succeed, delete source file */
+        if (Ret)
         {
-                       SetLastError(ERROR_ALREADY_EXISTS);
-                       return FALSE;
-       }
-       else if (GetFileAttributesW(lpNewFileName) & FILE_ATTRIBUTE_DIRECTORY)
-       {
-               SetLastError(ERROR_ACCESS_DENIED);
-               return FALSE;
-       }
+            if (!DeleteFileW(lpExistingFileName))
+            {
+                /* Reset file attributes if required */
+                SetFileAttributesW(lpExistingFileName, FILE_ATTRIBUTE_NORMAL);
+                DeleteFileW(lpExistingFileName);
+            }
+        }
     }
+    _SEH2_FINALLY
+    {
+        if (SourceHandle != INVALID_HANDLE_VALUE)
+            NtClose(SourceHandle);
+
+        RtlFreeHeap(RtlGetProcessHeap(), 0, ExistingPathU.Buffer);
+        RtlFreeHeap(RtlGetProcessHeap(), 0, NewPathU.Buffer);
+    }
+    _SEH2_END;
 
-       hFile = CreateFileW (lpExistingFileName,
-                            GENERIC_ALL,
-                            FILE_SHARE_WRITE|FILE_SHARE_READ,
-                            NULL,
-                            OPEN_EXISTING,
-                            FILE_FLAG_BACKUP_SEMANTICS |
-                            ((dwFlags & MOVEFILE_WRITE_THROUGH) ? FILE_FLAG_WRITE_THROUGH : 0),
-                            NULL);
-
-       if (hFile == INVALID_HANDLE_VALUE)
-       {
-           return FALSE;
-       }
-
-       FileRename = RtlAllocateHeap(
-               RtlGetProcessHeap(),
-               HEAP_ZERO_MEMORY,
-               sizeof(FILE_RENAME_INFORMATION) + DstPathU.Length);
-       if( !FileRename ) {
-               CloseHandle(hFile);
-               SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-               return FALSE;
-       }
-       if( dwFlags & MOVEFILE_REPLACE_EXISTING ) {
-               FileRename->ReplaceIfExists = TRUE;
-       }
-       else {
-               FileRename->ReplaceIfExists = FALSE;
-       }
-
-
-       memcpy(FileRename->FileName, DstPathU.Buffer, DstPathU.Length);
-        RtlFreeHeap (RtlGetProcessHeap (),
-                    0,
-                    DstPathU.Buffer);
-
-       FileRename->FileNameLength = DstPathU.Length;
-       errCode = NtSetInformationFile (hFile,
-                                       &IoStatusBlock,
-                                       FileRename,
-                                       sizeof(FILE_RENAME_INFORMATION) + DstPathU.Length,
-                                       FileRenameInformation);
-       CloseHandle(hFile);
-       RtlFreeHeap(RtlGetProcessHeap(), 0, FileRename);
-
-       if (GetFileAttributesW(lpExistingFileName) & FILE_ATTRIBUTE_DIRECTORY)
-       {
-           folder = TRUE;
-       }
-
-       
-       /*
-        *  FIXME:
-        *  Fail now move the folder 
-        *  Before we fail at CreateFileW 
-        */
-        
-        
-       if (NT_SUCCESS(errCode))
-       {
-               Result = TRUE;
-       }
-       else 
-       {
-               if (folder==FALSE)
-               {
-                   Result = CopyFileExW (lpExistingFileName,
-                                     lpNewFileName,
-                                     lpProgressRoutine,
-                                     lpData,
-                                     NULL,
-                                     (dwFlags & MOVEFILE_REPLACE_EXISTING) ? 0 : COPY_FILE_FAIL_IF_EXISTS);
-                   if (Result)
-                   {
-                       /* Cleanup the source file */                   
-                       Result = DeleteFileW (lpExistingFileName);
-                   }
-                  }
-                else
-                {
-                  /* move folder code start */
-                  WIN32_FIND_DATAW findBuffer;
-                  LPWSTR lpExistingFileName2 = NULL;
-                  LPWSTR lpNewFileName2 = NULL; 
-                  LPWSTR lpDeleteFile = NULL;
-                  INT size;
-                  INT size2;
-                  BOOL loop = TRUE;
-                  BOOL Result = FALSE;
-                  INT max_size = MAX_PATH;
-
-
-                                  /* Build the string */
-                  size = wcslen(lpExistingFileName); 
-                  if (size+6> max_size)
-                          max_size = size + 6;
-
-                  lpDeleteFile = (LPWSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,max_size * sizeof(WCHAR));
-                  if (lpDeleteFile == NULL)               
-                      return FALSE;                              
-
-                  lpNewFileName2 = (LPWSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,max_size * sizeof(WCHAR));
-                  if (lpNewFileName2 == NULL)
-                  {            
-                    HeapFree(GetProcessHeap(),0,(VOID *)  lpDeleteFile);
-                        return FALSE;
-                  }
-
-                  lpExistingFileName2 = (LPWSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,max_size * sizeof(WCHAR));
-                  if (lpExistingFileName2 == NULL)
-                  {            
-                    HeapFree(GetProcessHeap(),0,(VOID *)  lpNewFileName2);                                                     
-                    HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);                
-                    return FALSE;
-                  }                               
-               
-                  wcscpy( (WCHAR *)lpExistingFileName2,lpExistingFileName);
-                  wcscpy( (WCHAR *)&lpExistingFileName2[size],L"\\*.*\0");
-         
-                  /* Get the file name */
-                  memset(&findBuffer,0,sizeof(WIN32_FIND_DATAW));
-                  hFile = FindFirstFileW(lpExistingFileName2,  &findBuffer);
-                  if (hFile == INVALID_HANDLE_VALUE) 
-                      loop=FALSE;
-
-                  if (findBuffer.cFileName[0] == L'\0')
-                      loop=FALSE;
-               
-
-                   /* FIXME 
-                        * remove readonly flag from source folder and do not set the readonly flag to dest folder 
-                        */
-                  RemoveReadOnlyAttributeW(lpExistingFileName);
-           RemoveReadOnlyAttributeW(lpNewFileName);
-                  //CreateDirectoryExW(lpExistingFileName,lpNewFileName,NULL);
-                  CreateDirectoryW(lpNewFileName, NULL);
-                                  
-                  /* search the files/folders and move them */
-                  while (loop==TRUE)
-                  {    
-                    Result = TRUE;
-
-                    if ((!wcscmp(findBuffer.cFileName,L"..")) || (!wcscmp(findBuffer.cFileName,L".")))
-                    {            
-                      loop = FindNextFileW(hFile, &findBuffer);                  
-                                 
-                      if (!loop)
-                      {                                         
-                        size = wcslen(lpExistingFileName2)-4;
-                        FindClose(hFile);
-                        hFile = INVALID_HANDLE_VALUE;
-
-                        wcscpy( &lpExistingFileName2[size],L"\0");
-
-                        if (wcsncmp(lpExistingFileName,lpExistingFileName2,size))
-                        {  
-                                  DWORD Attributes;
-
-                                  /* delete folder */                                                                   
-                                  TRACE("MoveFileWithProgressW : Delete folder : %S\n",lpDeleteFile);
-
-                                  /* remove system folder flag other wise we can not delete the folder */
-                                  Attributes = GetFileAttributesW(lpExistingFileName2);
-                   if (Attributes != INVALID_FILE_ATTRIBUTES)
-                   {   
-                     SetFileAttributesW(lpExistingFileName2,(Attributes & ~FILE_ATTRIBUTE_SYSTEM));
-                                  }
-                                  
-                                  RemoveReadOnlyAttributeW(lpExistingFileName2);
-                                                                          
-                                  Result = RemoveDirectoryW(lpExistingFileName2);
-                                  if (Result == FALSE)
-                                      break;
-                                                                
-                                  loop=TRUE;                                                            
-                                  size = wcslen(lpExistingFileName); 
-                               
-                                  if (size+6>max_size)
-                                  {                                   
-                             if (lpNewFileName2 != NULL)                                       
-                                 HeapFree(GetProcessHeap(),0,(VOID *)  lpNewFileName2);
-                          
-                             if (lpExistingFileName2 != NULL)                            
-                                 HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2);            
-                                          
-                             if (lpDeleteFile != NULL)                         
-                                 HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);           
-                         
-                                     return FALSE;
-                                  }
-
-                                  wcscpy( lpExistingFileName2,lpExistingFileName);
-                                  wcscpy( &lpExistingFileName2[size],L"\\*.*\0");
-
-                                  /* Get the file name */
-                                  memset(&findBuffer,0,sizeof(WIN32_FIND_DATAW));
-                                  hFile = FindFirstFileW(lpExistingFileName2, &findBuffer);                     
-                        }
-               }                 
-               continue;                                 
-             }
-                         
-                    if (findBuffer.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-                    {                 
-
-               /* Build the new src string */                                            
-               size = wcslen(findBuffer.cFileName); 
-               size2= wcslen(lpExistingFileName2);
-
-               if (size2+size+6>max_size)
-               {
-                     FindClose(hFile);                  
-
-                        if (lpNewFileName2 != NULL)                                    
-                             HeapFree(GetProcessHeap(),0,(VOID *)  lpNewFileName2);
-                          
-                        if (lpExistingFileName2 != NULL)                                 
-                             HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2);                
-                                          
-                        if (lpDeleteFile != NULL)                              
-                             HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);               
-                         
-                                return FALSE;                                                   
-                  }
-
-                   wcscpy( &lpExistingFileName2[size2-3],findBuffer.cFileName);                                                  
-                wcscpy( &lpExistingFileName2[size2+size-3],L"\0");
-                          
-
-                          /* Continue */
-                          wcscpy( lpDeleteFile,lpExistingFileName2);
-                  wcscpy( &lpExistingFileName2[size2+size-3],L"\\*.*\0");
-          
-                 
-                  /* Build the new dst string */
-                  size = wcslen(lpExistingFileName2) + wcslen(lpNewFileName);
-                  size2 = wcslen(lpExistingFileName);
-                 
-                  if (size>max_size)
-                  {
-                    FindClose(hFile);                   
-
-                        if (lpNewFileName2 != NULL)                                    
-                             HeapFree(GetProcessHeap(),0,(VOID *)  lpNewFileName2);
-                          
-                        if (lpExistingFileName2 != NULL)                                 
-                             HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2);                
-                                          
-                        if (lpDeleteFile != NULL)                              
-                             HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);               
-                         
-                                return FALSE;                       
-                  }
-
-                  wcscpy( lpNewFileName2,lpNewFileName);                                 
-                  size = wcslen(lpNewFileName);                 
-                  wcscpy( &lpNewFileName2[size], &lpExistingFileName2[size2]);
-                  size = wcslen(lpNewFileName2);
-                  wcscpy( &lpNewFileName2[size-4],L"\0");
-                  
-                  /* Create Folder */            
-
-                          /* FIXME 
-                           * remove readonly flag from source folder and do not set the readonly flag to dest folder 
-                               */
-                          RemoveReadOnlyAttributeW(lpDeleteFile);
-                          RemoveReadOnlyAttributeW(lpNewFileName2);
-
-                          CreateDirectoryW(lpNewFileName2,NULL);
-                  //CreateDirectoryExW(lpDeleteFile, lpNewFileName2,NULL);
-                          
-
-                          /* set new search path  from src string */
-                  FindClose(hFile);
-                  memset(&findBuffer,0,sizeof(WIN32_FIND_DATAW));
-                  hFile = FindFirstFileW(lpExistingFileName2, &findBuffer);
-                }
-                    else
-                    {
-                 
-                  /* Build the new string */                                                             
-                  size = wcslen(findBuffer.cFileName); 
-                  size2= wcslen(lpExistingFileName2);
-                  wcscpy( lpDeleteFile,lpExistingFileName2);      
-                  wcscpy( &lpDeleteFile[size2-3],findBuffer.cFileName);           
-                 
-                  /* Build dest string */
-                  size = wcslen(lpDeleteFile) + wcslen(lpNewFileName);
-                  size2 = wcslen(lpExistingFileName);
-
-                  if (size>max_size)
-                  {                                              
-                             FindClose(hFile);                  
-
-                         if (lpNewFileName2 != NULL)                                   
-                             HeapFree(GetProcessHeap(),0,(VOID *)  lpNewFileName2);
-                          
-                         if (lpExistingFileName2 != NULL)                                
-                             HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2);                
-                                          
-                         if (lpDeleteFile != NULL)                             
-                             HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);               
-                         
-                                 return FALSE;
-                          }
-                 
-               wcscpy( lpNewFileName2,lpNewFileName);                            
-               size = wcslen(lpNewFileName);            
-               wcscpy(&lpNewFileName2[size],&lpDeleteFile[size2]);
-                
-              
-                          /* overrite existsen file, if the file got the flag have readonly 
-                           * we need reomve that flag 
-                               */
-                          
-                           /* copy file */
-                          
-                          TRACE("MoveFileWithProgressW : Copy file : %S to %S\n",lpDeleteFile, lpNewFileName2);
-                          RemoveReadOnlyAttributeW(lpDeleteFile);
-                          RemoveReadOnlyAttributeW(lpNewFileName2);
-                         
-                          Result = CopyFileExW (lpDeleteFile,
-                                     lpNewFileName2,
-                                     lpProgressRoutine,
-                                     lpData,
-                                     NULL,
-                                     0);
-
-                          if (Result == FALSE)                                
-                   break;
-              
-               /* delete file */                                           
-                          TRACE("MoveFileWithProgressW : remove readonly flag from file : %S\n",lpNewFileName2);
-                          Result = RemoveReadOnlyAttributeW(lpDeleteFile);
-                          if (Result == FALSE)
-                              break;
-
-               TRACE("MoveFileWithProgressW : Delete file : %S\n",lpDeleteFile);
-                          Result = DeleteFileW(lpDeleteFile);
-               if (Result == FALSE)                               
-                   break;
-              
-             }                       
-             loop = FindNextFileW(hFile, &findBuffer);           
-           }
-
-           
-                  /* Remove last folder */
-           if ((loop == FALSE) && (Result != FALSE))
-                  {
-                    DWORD Attributes;
-
-                        Attributes = GetFileAttributesW(lpDeleteFile);
-             if (Attributes != INVALID_FILE_ATTRIBUTES)
-             { 
-                SetFileAttributesW(lpDeleteFile,(Attributes & ~FILE_ATTRIBUTE_SYSTEM));
-                        }
-                                                                                                        
-                    Result = RemoveDirectoryW(lpExistingFileName);                  
-                  }
-           
-                  /* Cleanup */
-                  FindClose(hFile);    
-                  
-                  if (lpNewFileName2 != NULL)
-                  {            
-                    HeapFree(GetProcessHeap(),0,(VOID *)  lpNewFileName2);
-                    lpNewFileName2 = NULL;
-                  }
-
-                  if (lpExistingFileName2 != NULL)
-                  {      
-                    HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2);         
-                    lpExistingFileName2 = NULL;
-                  }
-
-                  if (lpDeleteFile != NULL)
-                  {            
-                    HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);                
-                    lpDeleteFile = NULL;
-                  }
-
-           return Result;
-
-                  // end move folder code               
-                 }
-       }
-       
-       
-       return Result;
+    return Ret;
 }
 
 
@@ -693,33 +576,39 @@ MoveFileWithProgressW (
  */
 BOOL
 WINAPI
-MoveFileWithProgressA (
-       LPCSTR                  lpExistingFileName,
-       LPCSTR                  lpNewFileName,
-       LPPROGRESS_ROUTINE      lpProgressRoutine,
-       LPVOID                  lpData,
-       DWORD                   dwFlags
-       )
+MoveFileWithProgressA(IN LPCSTR lpExistingFileName,
+                      IN LPCSTR lpNewFileName OPTIONAL,
+                      IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
+                      IN LPVOID lpData OPTIONAL,
+                      IN DWORD dwFlags)
 {
-       PWCHAR ExistingFileNameW;
-   PWCHAR NewFileNameW;
-       BOOL ret;
+    BOOL Ret;
+    UNICODE_STRING ExistingFileNameW, NewFileNameW;
 
-   if (!(ExistingFileNameW = FilenameA2W(lpExistingFileName, FALSE)))
-      return FALSE;
+    if (!Basep8BitStringToDynamicUnicodeString(&ExistingFileNameW, lpExistingFileName))
+    {
+        return FALSE;
+    }
 
-   if (!(NewFileNameW= FilenameA2W(lpNewFileName, TRUE)))
-      return FALSE;
+    if (lpNewFileName)
+    {
+        if (!Basep8BitStringToDynamicUnicodeString(&NewFileNameW, lpNewFileName))
+        {
+            RtlFreeUnicodeString(&ExistingFileNameW);
+            return FALSE;
+        }
+    }
+    else
+    {
+        NewFileNameW.Buffer = NULL;
+    }
 
-   ret = MoveFileWithProgressW (ExistingFileNameW ,
-                                   NewFileNameW,
-                                       lpProgressRoutine,
-                                       lpData,
-                                       dwFlags);
+    Ret = MoveFileWithProgressW(ExistingFileNameW.Buffer, NewFileNameW.Buffer, lpProgressRoutine, lpData, dwFlags);
 
-   RtlFreeHeap (RtlGetProcessHeap (), 0, NewFileNameW);
+    RtlFreeUnicodeString(&ExistingFileNameW);
+    RtlFreeUnicodeString(&NewFileNameW);
 
-       return ret;
+    return Ret;
 }
 
 
@@ -728,14 +617,14 @@ MoveFileWithProgressA (
  */
 BOOL
 WINAPI
-MoveFileW (
-       LPCWSTR lpExistingFileName,
-       LPCWSTR lpNewFileName
-       )
+MoveFileW(IN LPCWSTR lpExistingFileName,
+          IN LPCWSTR lpNewFileName)
 {
-       return MoveFileExW (lpExistingFileName,
-                           lpNewFileName,
-                           MOVEFILE_COPY_ALLOWED);
+    return MoveFileWithProgressW(lpExistingFileName,
+                                 lpNewFileName,
+                                 NULL,
+                                 NULL,
+                                 MOVEFILE_COPY_ALLOWED);
 }
 
 
@@ -744,17 +633,15 @@ MoveFileW (
  */
 BOOL
 WINAPI
-MoveFileExW (
-       LPCWSTR lpExistingFileName,
-       LPCWSTR lpNewFileName,
-       DWORD   dwFlags
-       )
+MoveFileExW(IN LPCWSTR lpExistingFileName,
+            IN LPCWSTR lpNewFileName OPTIONAL,
+            IN DWORD dwFlags)
 {
-       return MoveFileWithProgressW (lpExistingFileName,
-                                     lpNewFileName,
-                                     NULL,
-                                     NULL,
-                                     dwFlags);
+    return MoveFileWithProgressW(lpExistingFileName,
+                                lpNewFileName,
+                                NULL,
+                                NULL,
+                                dwFlags);
 }
 
 
@@ -763,14 +650,14 @@ MoveFileExW (
  */
 BOOL
 WINAPI
-MoveFileA (
-       LPCSTR  lpExistingFileName,
-       LPCSTR  lpNewFileName
-       )
+MoveFileA(IN LPCSTR lpExistingFileName,
+          IN LPCSTR lpNewFileName)
 {
-       return MoveFileExA (lpExistingFileName,
-                           lpNewFileName,
-                           MOVEFILE_COPY_ALLOWED);
+    return MoveFileWithProgressA(lpExistingFileName,
+                                 lpNewFileName,
+                                NULL,
+                                NULL,
+                                 MOVEFILE_COPY_ALLOWED);
 }
 
 
@@ -779,17 +666,15 @@ MoveFileA (
  */
 BOOL
 WINAPI
-MoveFileExA (
-       LPCSTR  lpExistingFileName,
-       LPCSTR  lpNewFileName,
-       DWORD   dwFlags
-       )
+MoveFileExA(IN LPCSTR lpExistingFileName,
+            IN LPCSTR lpNewFileName OPTIONAL,
+            IN DWORD dwFlags)
 {
-       return MoveFileWithProgressA (lpExistingFileName,
-                                     lpNewFileName,
-                                     NULL,
-                                     NULL,
-                                     dwFlags);
+    return MoveFileWithProgressA(lpExistingFileName,
+                                 lpNewFileName,
+                                 NULL,
+                                 NULL,
+                                 dwFlags);
 }
 
 /*
@@ -797,50 +682,57 @@ MoveFileExA (
  */
 BOOL
 WINAPI
-ReplaceFileA(
-    LPCSTR  lpReplacedFileName,
-    LPCSTR  lpReplacementFileName,
-    LPCSTR  lpBackupFileName,
-    DWORD   dwReplaceFlags,
-    LPVOID  lpExclude,
-    LPVOID  lpReserved
-    )
+ReplaceFileA(IN LPCSTR lpReplacedFileName,
+             IN LPCSTR lpReplacementFileName,
+             IN LPCSTR lpBackupFileName OPTIONAL,
+             IN DWORD dwReplaceFlags,
+             IN LPVOID lpExclude,
+             IN LPVOID lpReserved)
 {
-    WCHAR *replacedW, *replacementW, *backupW = NULL;
-    BOOL ret;
+    BOOL Ret;
+    UNICODE_STRING ReplacedFileNameW, ReplacementFileNameW, BackupFileNameW;
 
-    /* This function only makes sense when the first two parameters are defined */
-    if (!lpReplacedFileName || !(replacedW = FilenameA2W(lpReplacedFileName, TRUE)))
+    if (!lpReplacedFileName || !lpReplacementFileName || lpExclude || lpReserved || dwReplaceFlags & ~(REPLACEFILE_WRITE_THROUGH | REPLACEFILE_IGNORE_MERGE_ERRORS))
     {
         SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
 
-    if (!lpReplacementFileName || !(replacementW = FilenameA2W(lpReplacementFileName, TRUE)))
+    if (!Basep8BitStringToDynamicUnicodeString(&ReplacedFileNameW, lpReplacedFileName))
     {
-        HeapFree(GetProcessHeap(), 0, replacedW);
-        SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
 
-    /* The backup parameter, however, is optional */
+    if (!Basep8BitStringToDynamicUnicodeString(&ReplacementFileNameW, lpReplacementFileName))
+    {
+        RtlFreeUnicodeString(&ReplacedFileNameW);
+        return FALSE;
+    }
+
     if (lpBackupFileName)
     {
-        if (!(backupW = FilenameA2W(lpBackupFileName, TRUE)))
+        if (!Basep8BitStringToDynamicUnicodeString(&BackupFileNameW, lpBackupFileName))
         {
-            HeapFree(GetProcessHeap(), 0, replacedW);
-            HeapFree(GetProcessHeap(), 0, replacementW);
-            SetLastError(ERROR_INVALID_PARAMETER);
+            RtlFreeUnicodeString(&ReplacementFileNameW);
+            RtlFreeUnicodeString(&ReplacedFileNameW);
             return FALSE;
         }
     }
+    else
+    {
+        BackupFileNameW.Buffer = NULL;
+    }
 
-    ret = ReplaceFileW(replacedW, replacementW, backupW, dwReplaceFlags, lpExclude, lpReserved);
-    HeapFree(GetProcessHeap(), 0, replacedW);
-    HeapFree(GetProcessHeap(), 0, replacementW);
-    HeapFree(GetProcessHeap(), 0, backupW);
+    Ret = ReplaceFileW(ReplacedFileNameW.Buffer, ReplacementFileNameW.Buffer, BackupFileNameW.Buffer, dwReplaceFlags, 0, 0);
 
-    return ret;
+    if (lpBackupFileName)
+    {
+        RtlFreeUnicodeString(&BackupFileNameW);
+    }
+    RtlFreeUnicodeString(&ReplacementFileNameW);
+    RtlFreeUnicodeString(&ReplacedFileNameW);
+
+    return Ret;
 }
 
 /*
index 90798f9..87dd0cb 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <wine/unicode.h>
 
-const WCHAR wine_casemap_lower[3802] =
+const WCHAR wine_casemap_lower[3807] =
 {
     /* index */
     0x01bf, 0x02bf, 0x03bf, 0x044f, 0x054f, 0x064f, 0x0100, 0x0100,
@@ -26,7 +26,7 @@ const WCHAR wine_casemap_lower[3802] =
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
-    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0c1d, 0x0cfb,
+    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0c22, 0x0d00,
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
@@ -37,7 +37,7 @@ const WCHAR wine_casemap_lower[3802] =
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
-    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0dda,
+    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0ddf,
     /* defaults */
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -164,7 +164,7 @@ const WCHAR wine_casemap_lower[3802] =
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     /* 0x0370 .. 0x03ff */
     0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0074,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0026, 0x0000,
     0x0025, 0x0025, 0x0025, 0x0000, 0x0040, 0x0000, 0x003f, 0x003f,
     0x0000, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
@@ -219,8 +219,8 @@ const WCHAR wine_casemap_lower[3802] =
     0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
     0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
     0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
-    0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
+    0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
     0x0000, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030,
     0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030,
     0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030,
@@ -252,8 +252,8 @@ const WCHAR wine_casemap_lower[3802] =
     0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60,
     0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60,
     0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60,
-    0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x1c60, 0x0000, 0x1c60,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1c60, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -408,26 +408,27 @@ const WCHAR wine_casemap_lower[3802] =
     0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
     0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* 0xa60d .. 0xa6ff */
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    /* 0xa612 .. 0xa6ff */
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000,
-    0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
-    0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
-    0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
-    0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000,
-    0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
-    0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
+    0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
+    0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
+    0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
+    0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
+    0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000,
-    0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
-    0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
-    0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
+    0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
+    0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001,
+    0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -440,7 +441,7 @@ const WCHAR wine_casemap_lower[3802] =
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000,
     /* 0xa722 .. 0xa7ff */
     0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
     0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000,
@@ -455,11 +456,11 @@ const WCHAR wine_casemap_lower[3802] =
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001,
     0x0000, 0x0001, 0x0000, 0x75fc, 0x0001, 0x0000, 0x0001, 0x0000,
     0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0001, 0x0000, 0x5ad8, 0x0000, 0x0000, 0x0001, 0x0000,
+    0x0001, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
+    0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
+    0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000,
+    0x5abc, 0x5ab1, 0x5ab5, 0x5abf, 0x0000, 0x0000, 0x5aee, 0x5ad6,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -634,15 +635,15 @@ const WCHAR wine_casemap_upper[3994] =
     0x2a3f, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff,
     0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
     0x2a1f, 0x2a1c, 0x2a1e, 0xff2e, 0xff32, 0x0000, 0xff33, 0xff33,
-    0x0000, 0xff36, 0x0000, 0xff35, 0x0000, 0x0000, 0x0000, 0x0000,
-    0xff33, 0x0000, 0x0000, 0xff31, 0x0000, 0x0000, 0x0000, 0x0000,
-    0xff2f, 0xff2d, 0x0000, 0x29f7, 0x0000, 0x0000, 0x0000, 0xff2d,
+    0x0000, 0xff36, 0x0000, 0xff35, 0xa54f, 0x0000, 0x0000, 0x0000,
+    0xff33, 0xa54b, 0x0000, 0xff31, 0x0000, 0xa528, 0xa544, 0x0000,
+    0xff2f, 0xff2d, 0x0000, 0x29f7, 0xa541, 0x0000, 0x0000, 0xff2d,
     0x0000, 0x29fd, 0xff2b, 0x0000, 0x0000, 0xff2a, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x29e7, 0x0000, 0x0000,
-    0xff26, 0x0000, 0x0000, 0xff26, 0x0000, 0x0000, 0x0000, 0x0000,
+    0xff26, 0x0000, 0x0000, 0xff26, 0x0000, 0x0000, 0x0000, 0xa52a,
     0xff26, 0xffbb, 0xff27, 0xff27, 0xffb9, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0xff25, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa512, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -677,7 +678,7 @@ const WCHAR wine_casemap_upper[3994] =
     0xffd1, 0xffca, 0xfff8, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
     0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
     0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
-    0xffff, 0x0000, 0xffff, 0xffaa, 0xffb0, 0x0007, 0x0000, 0x0000,
+    0xffff, 0x0000, 0xffff, 0xffaa, 0xffb0, 0x0007, 0xff8c, 0x0000,
     0xffa0, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0xffff, 0x0000,
     0x0000, 0x0000, 0x0000,
     /* 0x0404 .. 0x04ff */
@@ -718,8 +719,8 @@ const WCHAR wine_casemap_upper[3994] =
     0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
     0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
     0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
-    0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
+    0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -908,7 +909,7 @@ const WCHAR wine_casemap_upper[3994] =
     0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
     0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000,
-    0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000,
     /* 0x2d00 .. 0x2dff */
@@ -916,8 +917,8 @@ const WCHAR wine_casemap_upper[3994] =
     0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0,
     0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0,
     0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0,
-    0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0xe3a0, 0x0000, 0xe3a0,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe3a0, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -949,14 +950,14 @@ const WCHAR wine_casemap_upper[3994] =
     0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
     0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
     0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
-    0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
+    0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
     0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
     0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
     0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -983,10 +984,10 @@ const WCHAR wine_casemap_upper[3994] =
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff,
     0x0000, 0xffff, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
     0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000,
-    0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000,
+    0xffff, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
+    0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
+    0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -1024,14 +1025,14 @@ const WCHAR wine_casemap_upper[3994] =
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
 };
-const WCHAR wine_digitmap[5837] =
+const WCHAR wine_digitmap[5933] =
 {
     /* index */
     0x01d0, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x028a, 0x0384,
-    0x0100, 0x044e, 0x053e, 0x062e, 0x071e, 0x080e, 0x08be, 0x099e,
-    0x0a5e, 0x0100, 0x0100, 0x0af8, 0x0100, 0x0100, 0x0100, 0x0b6a,
-    0x0c5a, 0x0d14, 0x0def, 0x0e9f, 0x0f5f, 0x0100, 0x0100, 0x0100,
-    0x0fef, 0x0100, 0x0100, 0x0100, 0x108f, 0x0100, 0x0100, 0x118f,
+    0x0100, 0x044e, 0x053e, 0x062e, 0x071e, 0x080e, 0x08fe, 0x09de,
+    0x0a9e, 0x0100, 0x0100, 0x0b38, 0x0100, 0x0100, 0x0100, 0x0baa,
+    0x0c9a, 0x0d54, 0x0e2f, 0x0edf, 0x0f9f, 0x0100, 0x0100, 0x0100,
+    0x102f, 0x0100, 0x0100, 0x0100, 0x10cf, 0x0100, 0x0100, 0x11cf,
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
@@ -1047,8 +1048,8 @@ const WCHAR wine_digitmap[5837] =
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
-    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x126f, 0x0100,
-    0x129f, 0x139f, 0x1479, 0x14d3, 0x0100, 0x0100, 0x0100, 0x0100,
+    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x12af, 0x0100,
+    0x12df, 0x13df, 0x14d9, 0x1533, 0x0100, 0x0100, 0x0100, 0x0100,
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
@@ -1058,7 +1059,7 @@ const WCHAR wine_digitmap[5837] =
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
     0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
-    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x15cd,
+    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x162d,
     /* defaults */
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -1324,11 +1325,19 @@ const WCHAR wine_digitmap[5837] =
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf24a, 0xf24a,
+    0xf24a, 0xf24a, 0xf24a, 0xf24a, 0xf24a, 0xf24a, 0xf24a, 0xf24a,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* 0x0e10 .. 0x0eff */
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    /* 0x0e50 .. 0x0eff */
     0xf1e0, 0xf1e0, 0xf1e0, 0xf1e0, 0xf1e0, 0xf1e0, 0xf1e0, 0xf1e0,
     0xf1e0, 0xf1e0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -1715,9 +1724,13 @@ const WCHAR wine_digitmap[5837] =
     0x5660, 0x5660, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x5640, 0x5640, 0x5640, 0x5640, 0x5640, 0x5640, 0x5640, 0x5640,
+    0x5640, 0x5640, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* 0xaa06 .. 0xaaff */
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    /* 0xaa26 .. 0xaaff */
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -1900,7 +1913,7 @@ const WCHAR wine_compatmap[1497] =
     0x5e4a, 0x0000, 0x6c62, 0x0000, 0x0000, 0x57c9, 0x7914, 0x7cb3,
     0x7f24, 0x7f45, 0x7f4b, 0x7f74, 0x9d3a, 0x82a1, 0x859f, 0x0000,
     0x8bf2, 0x0000, 0x90d6, 0x0000, 0x0000, 0x9613, 0x96d7, 0x0000,
-    0x0000, 0x0000, 0x9ec5, 0x9ed1, 0x9efc, 0xa387, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x9ec5, 0x9ed1, 0x9efc, 0xa387, 0x96b0, 0x9c88,
     0x557e, 0x56b6, 0x571b, 0x5896, 0x58b0, 0x591c, 0x5b67, 0x5bcf,
     0x5c30, 0x5e07, 0x5e6e, 0x6229, 0x6232, 0x6657, 0x672a, 0x674f,
     0x67b2, 0x6b0e, 0x6ba0, 0x6c4e, 0x6e41, 0x7332, 0x73d4, 0x74db,
index 879e581..adc116e 100644 (file)
@@ -285,7 +285,7 @@ static void format_add_char(struct _format_message_data *fmd, WCHAR c)
             LPWSTR notspace;
             if (fmd->space) {
                 notspace = fmd->space;
-                while (*notspace == ' ' && notspace != fmd->t)
+                while (notspace != fmd->t && *notspace == ' ')
                     notspace++;
             } else
                 notspace = fmd->space = fmd->t;
index 14dd6f0..825c90e 100644 (file)
@@ -1855,29 +1855,6 @@ static HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
     return hkey;
 }
 
-static BOOL NLS_RegEnumSubKey(HANDLE hKey, UINT ulIndex, LPWSTR szKeyName,
-                              ULONG keyNameSize)
-{
-    BYTE buffer[80];
-    KEY_BASIC_INFORMATION *info = (KEY_BASIC_INFORMATION *)buffer;
-    DWORD dwLen;
-
-    if (NtEnumerateKey( hKey, ulIndex, KeyBasicInformation, buffer,
-                        sizeof(buffer), &dwLen) != STATUS_SUCCESS ||
-        info->NameLength > keyNameSize)
-    {
-        return FALSE;
-    }
-
-    TRACE("info->Name %s info->NameLength %d\n", debugstr_w(info->Name), info->NameLength);
-
-    memcpy( szKeyName, info->Name, info->NameLength);
-    szKeyName[info->NameLength / sizeof(WCHAR)] = '\0';
-
-    TRACE("returning %s\n", debugstr_w(szKeyName));
-    return TRUE;
-}
-
 static BOOL NLS_RegEnumValue(HANDLE hKey, UINT ulIndex,
                              LPWSTR szValueName, ULONG valueNameSize,
                              LPWSTR szValueData, ULONG valueDataSize)
@@ -2272,6 +2249,323 @@ static BOOL NLS_EnumLanguageGroupLocales(ENUMLANGUAGEGROUPLOCALE_CALLBACKS *lpPr
     return TRUE;
 }
 
+enum locationkind {
+    LOCATION_NATION = 0,
+    LOCATION_REGION,
+    LOCATION_BOTH
+};
+
+struct geoinfo_t {
+    GEOID id;
+    WCHAR iso2W[3];
+    WCHAR iso3W[4];
+    GEOID parent;
+    INT   uncode;
+    enum locationkind kind;
+};
+
+static const struct geoinfo_t geoinfodata[] = {
+    { 2, {'A','G',0}, {'A','T','G',0}, 10039880,  28 }, /* Antigua and Barbuda */
+    { 3, {'A','F',0}, {'A','F','G',0}, 47614,   4 }, /* Afghanistan */
+    { 4, {'D','Z',0}, {'D','Z','A',0}, 42487,  12 }, /* Algeria */
+    { 5, {'A','Z',0}, {'A','Z','E',0}, 47611,  31 }, /* Azerbaijan */
+    { 6, {'A','L',0}, {'A','L','B',0}, 47610,   8 }, /* Albania */
+    { 7, {'A','M',0}, {'A','R','M',0}, 47611,  51 }, /* Armenia */
+    { 8, {'A','D',0}, {'A','N','D',0}, 47610,  20 }, /* Andorra */
+    { 9, {'A','O',0}, {'A','G','O',0}, 42484,  24 }, /* Angola */
+    { 10, {'A','S',0}, {'A','S','M',0}, 26286,  16 }, /* American Samoa */
+    { 11, {'A','R',0}, {'A','R','G',0}, 31396,  32 }, /* Argentina */
+    { 12, {'A','U',0}, {'A','U','S',0}, 10210825,  36 }, /* Australia */
+    { 14, {'A','T',0}, {'A','U','T',0}, 10210824,  40 }, /* Austria */
+    { 17, {'B','H',0}, {'B','H','R',0}, 47611,  48 }, /* Bahrain */
+    { 18, {'B','B',0}, {'B','R','B',0}, 10039880,  52 }, /* Barbados */
+    { 19, {'B','W',0}, {'B','W','A',0}, 10039883,  72 }, /* Botswana */
+    { 20, {'B','M',0}, {'B','M','U',0}, 23581,  60 }, /* Bermuda */
+    { 21, {'B','E',0}, {'B','E','L',0}, 10210824,  56 }, /* Belgium */
+    { 22, {'B','S',0}, {'B','H','S',0}, 10039880,  44 }, /* Bahamas, The */
+    { 23, {'B','D',0}, {'B','G','D',0}, 47614,  50 }, /* Bangladesh */
+    { 24, {'B','Z',0}, {'B','L','Z',0}, 27082,  84 }, /* Belize */
+    { 25, {'B','A',0}, {'B','I','H',0}, 47610,  70 }, /* Bosnia and Herzegovina */
+    { 26, {'B','O',0}, {'B','O','L',0}, 31396,  68 }, /* Bolivia */
+    { 27, {'M','M',0}, {'M','M','R',0}, 47599, 104 }, /* Myanmar */
+    { 28, {'B','J',0}, {'B','E','N',0}, 42483, 204 }, /* Benin */
+    { 29, {'B','Y',0}, {'B','L','R',0}, 47609, 112 }, /* Belarus */
+    { 30, {'S','B',0}, {'S','L','B',0}, 20900,  90 }, /* Solomon Islands */
+    { 32, {'B','R',0}, {'B','R','A',0}, 31396,  76 }, /* Brazil */
+    { 34, {'B','T',0}, {'B','T','N',0}, 47614,  64 }, /* Bhutan */
+    { 35, {'B','G',0}, {'B','G','R',0}, 47609, 100 }, /* Bulgaria */
+    { 37, {'B','N',0}, {'B','R','N',0}, 47599,  96 }, /* Brunei */
+    { 38, {'B','I',0}, {'B','D','I',0}, 47603, 108 }, /* Burundi */
+    { 39, {'C','A',0}, {'C','A','N',0}, 23581, 124 }, /* Canada */
+    { 40, {'K','H',0}, {'K','H','M',0}, 47599, 116 }, /* Cambodia */
+    { 41, {'T','D',0}, {'T','C','D',0}, 42484, 148 }, /* Chad */
+    { 42, {'L','K',0}, {'L','K','A',0}, 47614, 144 }, /* Sri Lanka */
+    { 43, {'C','G',0}, {'C','O','G',0}, 42484, 178 }, /* Congo */
+    { 44, {'C','D',0}, {'C','O','D',0}, 42484, 180 }, /* Congo (DRC) */
+    { 45, {'C','N',0}, {'C','H','N',0}, 47600, 156 }, /* China */
+    { 46, {'C','L',0}, {'C','H','L',0}, 31396, 152 }, /* Chile */
+    { 49, {'C','M',0}, {'C','M','R',0}, 42484, 120 }, /* Cameroon */
+    { 50, {'K','M',0}, {'C','O','M',0}, 47603, 174 }, /* Comoros */
+    { 51, {'C','O',0}, {'C','O','L',0}, 31396, 170 }, /* Colombia */
+    { 54, {'C','R',0}, {'C','R','I',0}, 27082, 188 }, /* Costa Rica */
+    { 55, {'C','F',0}, {'C','A','F',0}, 42484, 140 }, /* Central African Republic */
+    { 56, {'C','U',0}, {'C','U','B',0}, 10039880, 192 }, /* Cuba */
+    { 57, {'C','V',0}, {'C','P','V',0}, 42483, 132 }, /* Cape Verde */
+    { 59, {'C','Y',0}, {'C','Y','P',0}, 47611, 196 }, /* Cyprus */
+    { 61, {'D','K',0}, {'D','N','K',0}, 10039882, 208 }, /* Denmark */
+    { 62, {'D','J',0}, {'D','J','I',0}, 47603, 262 }, /* Djibouti */
+    { 63, {'D','M',0}, {'D','M','A',0}, 10039880, 212 }, /* Dominica */
+    { 65, {'D','O',0}, {'D','O','M',0}, 10039880, 214 }, /* Dominican Republic */
+    { 66, {'E','C',0}, {'E','C','U',0}, 31396, 218 }, /* Ecuador */
+    { 67, {'E','G',0}, {'E','G','Y',0}, 42487, 818 }, /* Egypt */
+    { 68, {'I','E',0}, {'I','R','L',0}, 10039882, 372 }, /* Ireland */
+    { 69, {'G','Q',0}, {'G','N','Q',0}, 42484, 226 }, /* Equatorial Guinea */
+    { 70, {'E','E',0}, {'E','S','T',0}, 10039882, 233 }, /* Estonia */
+    { 71, {'E','R',0}, {'E','R','I',0}, 47603, 232 }, /* Eritrea */
+    { 72, {'S','V',0}, {'S','L','V',0}, 27082, 222 }, /* El Salvador */
+    { 73, {'E','T',0}, {'E','T','H',0}, 47603, 231 }, /* Ethiopia */
+    { 75, {'C','Z',0}, {'C','Z','E',0}, 47609, 203 }, /* Czech Republic */
+    { 77, {'F','I',0}, {'F','I','N',0}, 10039882, 246 }, /* Finland */
+    { 78, {'F','J',0}, {'F','J','I',0}, 20900, 242 }, /* Fiji Islands */
+    { 80, {'F','M',0}, {'F','S','M',0}, 21206, 583 }, /* Micronesia */
+    { 81, {'F','O',0}, {'F','R','O',0}, 10039882, 234 }, /* Faroe Islands */
+    { 84, {'F','R',0}, {'F','R','A',0}, 10210824, 250 }, /* France */
+    { 86, {'G','M',0}, {'G','M','B',0}, 42483, 270 }, /* Gambia, The */
+    { 87, {'G','A',0}, {'G','A','B',0}, 42484, 266 }, /* Gabon */
+    { 88, {'G','E',0}, {'G','E','O',0}, 47611, 268 }, /* Georgia */
+    { 89, {'G','H',0}, {'G','H','A',0}, 42483, 288 }, /* Ghana */
+    { 90, {'G','I',0}, {'G','I','B',0}, 47610, 292 }, /* Gibraltar */
+    { 91, {'G','D',0}, {'G','R','D',0}, 10039880, 308 }, /* Grenada */
+    { 93, {'G','L',0}, {'G','R','L',0}, 23581, 304 }, /* Greenland */
+    { 94, {'D','E',0}, {'D','E','U',0}, 10210824, 276 }, /* Germany */
+    { 98, {'G','R',0}, {'G','R','C',0}, 47610, 300 }, /* Greece */
+    { 99, {'G','T',0}, {'G','T','M',0}, 27082, 320 }, /* Guatemala */
+    { 100, {'G','N',0}, {'G','I','N',0}, 42483, 324 }, /* Guinea */
+    { 101, {'G','Y',0}, {'G','U','Y',0}, 31396, 328 }, /* Guyana */
+    { 103, {'H','T',0}, {'H','T','I',0}, 10039880, 332 }, /* Haiti */
+    { 104, {'H','K',0}, {'H','K','G',0}, 47600, 344 }, /* Hong Kong S.A.R. */
+    { 106, {'H','N',0}, {'H','N','D',0}, 27082, 340 }, /* Honduras */
+    { 108, {'H','R',0}, {'H','R','V',0}, 47610, 191 }, /* Croatia */
+    { 109, {'H','U',0}, {'H','U','N',0}, 47609, 348 }, /* Hungary */
+    { 110, {'I','S',0}, {'I','S','L',0}, 10039882, 352 }, /* Iceland */
+    { 111, {'I','D',0}, {'I','D','N',0}, 47599, 360 }, /* Indonesia */
+    { 113, {'I','N',0}, {'I','N','D',0}, 47614, 356 }, /* India */
+    { 114, {'I','O',0}, {'I','O','T',0}, 39070,  86 }, /* British Indian Ocean Territory */
+    { 116, {'I','R',0}, {'I','R','N',0}, 47614, 364 }, /* Iran */
+    { 117, {'I','L',0}, {'I','S','R',0}, 47611, 376 }, /* Israel */
+    { 118, {'I','T',0}, {'I','T','A',0}, 47610, 380 }, /* Italy */
+    { 119, {'C','I',0}, {'C','I','V',0}, 42483, 384 }, /* Côte d'Ivoire */
+    { 121, {'I','Q',0}, {'I','R','Q',0}, 47611, 368 }, /* Iraq */
+    { 122, {'J','P',0}, {'J','P','N',0}, 47600, 392 }, /* Japan */
+    { 124, {'J','M',0}, {'J','A','M',0}, 10039880, 388 }, /* Jamaica */
+    { 125, {'S','J',0}, {'S','J','M',0}, 10039882, 744 }, /* Jan Mayen */
+    { 126, {'J','O',0}, {'J','O','R',0}, 47611, 400 }, /* Jordan */
+    { 127, {'X','X',0}, {'X','X',0}, 161832256 }, /* Johnston Atoll */
+    { 129, {'K','E',0}, {'K','E','N',0}, 47603, 404 }, /* Kenya */
+    { 130, {'K','G',0}, {'K','G','Z',0}, 47590, 417 }, /* Kyrgyzstan */
+    { 131, {'K','P',0}, {'P','R','K',0}, 47600, 408 }, /* North Korea */
+    { 133, {'K','I',0}, {'K','I','R',0}, 21206, 296 }, /* Kiribati */
+    { 134, {'K','R',0}, {'K','O','R',0}, 47600, 410 }, /* Korea */
+    { 136, {'K','W',0}, {'K','W','T',0}, 47611, 414 }, /* Kuwait */
+    { 137, {'K','Z',0}, {'K','A','Z',0}, 47590, 398 }, /* Kazakhstan */
+    { 138, {'L','A',0}, {'L','A','O',0}, 47599, 418 }, /* Laos */
+    { 139, {'L','B',0}, {'L','B','N',0}, 47611, 422 }, /* Lebanon */
+    { 140, {'L','V',0}, {'L','V','A',0}, 10039882, 428 }, /* Latvia */
+    { 141, {'L','T',0}, {'L','T','U',0}, 10039882, 440 }, /* Lithuania */
+    { 142, {'L','R',0}, {'L','B','R',0}, 42483, 430 }, /* Liberia */
+    { 143, {'S','K',0}, {'S','V','K',0}, 47609, 703 }, /* Slovakia */
+    { 145, {'L','I',0}, {'L','I','E',0}, 10210824, 438 }, /* Liechtenstein */
+    { 146, {'L','S',0}, {'L','S','O',0}, 10039883, 426 }, /* Lesotho */
+    { 147, {'L','U',0}, {'L','U','X',0}, 10210824, 442 }, /* Luxembourg */
+    { 148, {'L','Y',0}, {'L','B','Y',0}, 42487, 434 }, /* Libya */
+    { 149, {'M','G',0}, {'M','D','G',0}, 47603, 450 }, /* Madagascar */
+    { 151, {'M','O',0}, {'M','A','C',0}, 47600, 446 }, /* Macao S.A.R. */
+    { 152, {'M','D',0}, {'M','D','A',0}, 47609, 498 }, /* Moldova */
+    { 154, {'M','N',0}, {'M','N','G',0}, 47600, 496 }, /* Mongolia */
+    { 156, {'M','W',0}, {'M','W','I',0}, 47603, 454 }, /* Malawi */
+    { 157, {'M','L',0}, {'M','L','I',0}, 42483, 466 }, /* Mali */
+    { 158, {'M','C',0}, {'M','C','O',0}, 10210824, 492 }, /* Monaco */
+    { 159, {'M','A',0}, {'M','A','R',0}, 42487, 504 }, /* Morocco */
+    { 160, {'M','U',0}, {'M','U','S',0}, 47603, 480 }, /* Mauritius */
+    { 162, {'M','R',0}, {'M','R','T',0}, 42483, 478 }, /* Mauritania */
+    { 163, {'M','T',0}, {'M','L','T',0}, 47610, 470 }, /* Malta */
+    { 164, {'O','M',0}, {'O','M','N',0}, 47611, 512 }, /* Oman */
+    { 165, {'M','V',0}, {'M','D','V',0}, 47614, 462 }, /* Maldives */
+    { 166, {'M','X',0}, {'M','E','X',0}, 27082, 484 }, /* Mexico */
+    { 167, {'M','Y',0}, {'M','Y','S',0}, 47599, 458 }, /* Malaysia */
+    { 168, {'M','Z',0}, {'M','O','Z',0}, 47603, 508 }, /* Mozambique */
+    { 173, {'N','E',0}, {'N','E','R',0}, 42483, 562 }, /* Niger */
+    { 174, {'V','U',0}, {'V','U','T',0}, 20900, 548 }, /* Vanuatu */
+    { 175, {'N','G',0}, {'N','G','A',0}, 42483, 566 }, /* Nigeria */
+    { 176, {'N','L',0}, {'N','L','D',0}, 10210824, 528 }, /* Netherlands */
+    { 177, {'N','O',0}, {'N','O','R',0}, 10039882, 578 }, /* Norway */
+    { 178, {'N','P',0}, {'N','P','L',0}, 47614, 524 }, /* Nepal */
+    { 180, {'N','R',0}, {'N','R','U',0}, 21206, 520 }, /* Nauru */
+    { 181, {'S','R',0}, {'S','U','R',0}, 31396, 740 }, /* Suriname */
+    { 182, {'N','I',0}, {'N','I','C',0}, 27082, 558 }, /* Nicaragua */
+    { 183, {'N','Z',0}, {'N','Z','L',0}, 10210825, 554 }, /* New Zealand */
+    { 184, {'P','S',0}, {'P','S','E',0}, 47611, 275 }, /* Palestinian Authority */
+    { 185, {'P','Y',0}, {'P','R','Y',0}, 31396, 600 }, /* Paraguay */
+    { 187, {'P','E',0}, {'P','E','R',0}, 31396, 604 }, /* Peru */
+    { 190, {'P','K',0}, {'P','A','K',0}, 47614, 586 }, /* Pakistan */
+    { 191, {'P','L',0}, {'P','O','L',0}, 47609, 616 }, /* Poland */
+    { 192, {'P','A',0}, {'P','A','N',0}, 27082, 591 }, /* Panama */
+    { 193, {'P','T',0}, {'P','R','T',0}, 47610, 620 }, /* Portugal */
+    { 194, {'P','G',0}, {'P','N','G',0}, 20900, 598 }, /* Papua New Guinea */
+    { 195, {'P','W',0}, {'P','L','W',0}, 21206, 585 }, /* Palau */
+    { 196, {'G','W',0}, {'G','N','B',0}, 42483, 624 }, /* Guinea-Bissau */
+    { 197, {'Q','A',0}, {'Q','A','T',0}, 47611, 634 }, /* Qatar */
+    { 198, {'R','E',0}, {'R','E','U',0}, 47603, 638 }, /* Reunion */
+    { 199, {'M','H',0}, {'M','H','L',0}, 21206, 584 }, /* Marshall Islands */
+    { 200, {'R','O',0}, {'R','O','U',0}, 47609, 642 }, /* Romania */
+    { 201, {'P','H',0}, {'P','H','L',0}, 47599, 608 }, /* Philippines */
+    { 202, {'P','R',0}, {'P','R','I',0}, 10039880, 630 }, /* Puerto Rico */
+    { 203, {'R','U',0}, {'R','U','S',0}, 47609, 643 }, /* Russia */
+    { 204, {'R','W',0}, {'R','W','A',0}, 47603, 646 }, /* Rwanda */
+    { 205, {'S','A',0}, {'S','A','U',0}, 47611, 682 }, /* Saudi Arabia */
+    { 206, {'P','M',0}, {'S','P','M',0}, 23581, 666 }, /* St. Pierre and Miquelon */
+    { 207, {'K','N',0}, {'K','N','A',0}, 10039880, 659 }, /* St. Kitts and Nevis */
+    { 208, {'S','C',0}, {'S','Y','C',0}, 47603, 690 }, /* Seychelles */
+    { 209, {'Z','A',0}, {'Z','A','F',0}, 10039883, 710 }, /* South Africa */
+    { 210, {'S','N',0}, {'S','E','N',0}, 42483, 686 }, /* Senegal */
+    { 212, {'S','I',0}, {'S','V','N',0}, 47610, 705 }, /* Slovenia */
+    { 213, {'S','L',0}, {'S','L','E',0}, 42483, 694 }, /* Sierra Leone */
+    { 214, {'S','M',0}, {'S','M','R',0}, 47610, 674 }, /* San Marino */
+    { 215, {'S','G',0}, {'S','G','P',0}, 47599, 702 }, /* Singapore */
+    { 216, {'S','O',0}, {'S','O','M',0}, 47603, 706 }, /* Somalia */
+    { 217, {'E','S',0}, {'E','S','P',0}, 47610, 724 }, /* Spain */
+    { 218, {'L','C',0}, {'L','C','A',0}, 10039880, 662 }, /* St. Lucia */
+    { 219, {'S','D',0}, {'S','D','N',0}, 42487, 736 }, /* Sudan */
+    { 220, {'S','J',0}, {'S','J','M',0}, 10039882, 744 }, /* Svalbard */
+    { 221, {'S','E',0}, {'S','W','E',0}, 10039882, 752 }, /* Sweden */
+    { 222, {'S','Y',0}, {'S','Y','R',0}, 47611, 760 }, /* Syria */
+    { 223, {'C','H',0}, {'C','H','E',0}, 10210824, 756 }, /* Switzerland */
+    { 224, {'A','E',0}, {'A','R','E',0}, 47611, 784 }, /* United Arab Emirates */
+    { 225, {'T','T',0}, {'T','T','O',0}, 10039880, 780 }, /* Trinidad and Tobago */
+    { 227, {'T','H',0}, {'T','H','A',0}, 47599, 764 }, /* Thailand */
+    { 228, {'T','J',0}, {'T','J','K',0}, 47590, 762 }, /* Tajikistan */
+    { 231, {'T','O',0}, {'T','O','N',0}, 26286, 776 }, /* Tonga */
+    { 232, {'T','G',0}, {'T','G','O',0}, 42483, 768 }, /* Togo */
+    { 233, {'S','T',0}, {'S','T','P',0}, 42484, 678 }, /* São Tomé and Príncipe */
+    { 234, {'T','N',0}, {'T','U','N',0}, 42487, 788 }, /* Tunisia */
+    { 235, {'T','R',0}, {'T','U','R',0}, 47611, 792 }, /* Turkey */
+    { 236, {'T','V',0}, {'T','U','V',0}, 26286, 798 }, /* Tuvalu */
+    { 237, {'T','W',0}, {'T','W','N',0}, 47600, 158 }, /* Taiwan */
+    { 238, {'T','M',0}, {'T','K','M',0}, 47590, 795 }, /* Turkmenistan */
+    { 239, {'T','Z',0}, {'T','Z','A',0}, 47603, 834 }, /* Tanzania */
+    { 240, {'U','G',0}, {'U','G','A',0}, 47603, 800 }, /* Uganda */
+    { 241, {'U','A',0}, {'U','K','R',0}, 47609, 804 }, /* Ukraine */
+    { 242, {'G','B',0}, {'G','B','R',0}, 10039882, 826 }, /* United Kingdom */
+    { 244, {'U','S',0}, {'U','S','A',0}, 23581, 840 }, /* United States */
+    { 245, {'B','F',0}, {'B','F','A',0}, 42483, 854 }, /* Burkina Faso */
+    { 246, {'U','Y',0}, {'U','R','Y',0}, 31396, 858 }, /* Uruguay */
+    { 247, {'U','Z',0}, {'U','Z','B',0}, 47590, 860 }, /* Uzbekistan */
+    { 248, {'V','C',0}, {'V','C','T',0}, 10039880, 670 }, /* St. Vincent and the Grenadines */
+    { 249, {'V','E',0}, {'V','E','N',0}, 31396, 862 }, /* Bolivarian Republic of Venezuela */
+    { 251, {'V','N',0}, {'V','N','M',0}, 47599, 704 }, /* Vietnam */
+    { 252, {'V','I',0}, {'V','I','R',0}, 10039880, 850 }, /* Virgin Islands */
+    { 253, {'V','A',0}, {'V','A','T',0}, 47610, 336 }, /* Vatican City */
+    { 254, {'N','A',0}, {'N','A','M',0}, 10039883, 516 }, /* Namibia */
+    { 257, {'E','H',0}, {'E','S','H',0}, 42487, 732 }, /* Western Sahara (disputed) */
+    { 258, {'X','X',0}, {'X','X',0}, 161832256 }, /* Wake Island */
+    { 259, {'W','S',0}, {'W','S','M',0}, 26286, 882 }, /* Samoa */
+    { 260, {'S','Z',0}, {'S','W','Z',0}, 10039883, 748 }, /* Swaziland */
+    { 261, {'Y','E',0}, {'Y','E','M',0}, 47611, 887 }, /* Yemen */
+    { 263, {'Z','M',0}, {'Z','M','B',0}, 47603, 894 }, /* Zambia */
+    { 264, {'Z','W',0}, {'Z','W','E',0}, 47603, 716 }, /* Zimbabwe */
+    { 269, {'C','S',0}, {'S','C','G',0}, 47610, 891 }, /* Serbia and Montenegro (Former) */
+    { 270, {'M','E',0}, {'M','N','E',0}, 47610, 499 }, /* Montenegro */
+    { 271, {'R','S',0}, {'S','R','B',0}, 47610, 688 }, /* Serbia */
+    { 273, {'C','W',0}, {'C','U','W',0}, 10039880, 531 }, /* Curaçao */
+    { 276, {'S','S',0}, {'S','S','D',0}, 42487, 728 }, /* South Sudan */
+    { 300, {'A','I',0}, {'A','I','A',0}, 10039880, 660 }, /* Anguilla */
+    { 301, {'A','Q',0}, {'A','T','A',0}, 39070,  10 }, /* Antarctica */
+    { 302, {'A','W',0}, {'A','B','W',0}, 10039880, 533 }, /* Aruba */
+    { 303, {'X','X',0}, {'X','X',0}, 39070 }, /* Ascension Island */
+    { 304, {'X','X',0}, {'X','X',0}, 10210825 }, /* Ashmore and Cartier Islands */
+    { 305, {'X','X',0}, {'X','X',0}, 161832256 }, /* Baker Island */
+    { 306, {'B','V',0}, {'B','V','T',0}, 39070,  74 }, /* Bouvet Island */
+    { 307, {'K','Y',0}, {'C','Y','M',0}, 10039880, 136 }, /* Cayman Islands */
+    { 308, {'X','X',0}, {'X','X',0}, 10210824, 0, LOCATION_BOTH }, /* Channel Islands */
+    { 309, {'C','X',0}, {'C','X','R',0}, 12, 162 }, /* Christmas Island */
+    { 310, {'X','X',0}, {'X','X',0}, 27114 }, /* Clipperton Island */
+    { 311, {'C','C',0}, {'C','C','K',0}, 10210825, 166 }, /* Cocos (Keeling) Islands */
+    { 312, {'C','K',0}, {'C','O','K',0}, 26286, 184 }, /* Cook Islands */
+    { 313, {'X','X',0}, {'X','X',0}, 10210825 }, /* Coral Sea Islands */
+    { 314, {'X','X',0}, {'X','X',0}, 114 }, /* Diego Garcia */
+    { 315, {'F','K',0}, {'F','L','K',0}, 31396, 238 }, /* Falkland Islands (Islas Malvinas) */
+    { 317, {'G','F',0}, {'G','U','F',0}, 31396, 254 }, /* French Guiana */
+    { 318, {'P','F',0}, {'P','Y','F',0}, 26286, 258 }, /* French Polynesia */
+    { 319, {'T','F',0}, {'A','T','F',0}, 39070, 260 }, /* French Southern and Antarctic Lands */
+    { 321, {'G','P',0}, {'G','L','P',0}, 10039880, 312 }, /* Guadeloupe */
+    { 322, {'G','U',0}, {'G','U','M',0}, 21206, 316 }, /* Guam */
+    { 323, {'X','X',0}, {'X','X',0}, 39070 }, /* Guantanamo Bay */
+    { 324, {'G','G',0}, {'G','G','Y',0}, 308, 831 }, /* Guernsey */
+    { 325, {'H','M',0}, {'H','M','D',0}, 39070, 334 }, /* Heard Island and McDonald Islands */
+    { 326, {'X','X',0}, {'X','X',0}, 161832256 }, /* Howland Island */
+    { 327, {'X','X',0}, {'X','X',0}, 161832256 }, /* Jarvis Island */
+    { 328, {'J','E',0}, {'J','E','Y',0}, 308, 832 }, /* Jersey */
+    { 329, {'X','X',0}, {'X','X',0}, 161832256 }, /* Kingman Reef */
+    { 330, {'M','Q',0}, {'M','T','Q',0}, 10039880, 474 }, /* Martinique */
+    { 331, {'Y','T',0}, {'M','Y','T',0}, 47603, 175 }, /* Mayotte */
+    { 332, {'M','S',0}, {'M','S','R',0}, 10039880, 500 }, /* Montserrat */
+    { 333, {'A','N',0}, {'A','N','T',0}, 10039880, 530, LOCATION_BOTH }, /* Netherlands Antilles (Former) */
+    { 334, {'N','C',0}, {'N','C','L',0}, 20900, 540 }, /* New Caledonia */
+    { 335, {'N','U',0}, {'N','I','U',0}, 26286, 570 }, /* Niue */
+    { 336, {'N','F',0}, {'N','F','K',0}, 10210825, 574 }, /* Norfolk Island */
+    { 337, {'M','P',0}, {'M','N','P',0}, 21206, 580 }, /* Northern Mariana Islands */
+    { 338, {'X','X',0}, {'X','X',0}, 161832256 }, /* Palmyra Atoll */
+    { 339, {'P','N',0}, {'P','C','N',0}, 26286, 612 }, /* Pitcairn Islands */
+    { 340, {'X','X',0}, {'X','X',0}, 337 }, /* Rota Island */
+    { 341, {'X','X',0}, {'X','X',0}, 337 }, /* Saipan */
+    { 342, {'G','S',0}, {'S','G','S',0}, 39070, 239 }, /* South Georgia and the South Sandwich Islands */
+    { 343, {'S','H',0}, {'S','H','N',0}, 42483, 654 }, /* St. Helena */
+    { 346, {'X','X',0}, {'X','X',0}, 337 }, /* Tinian Island */
+    { 347, {'T','K',0}, {'T','K','L',0}, 26286, 772 }, /* Tokelau */
+    { 348, {'X','X',0}, {'X','X',0}, 39070 }, /* Tristan da Cunha */
+    { 349, {'T','C',0}, {'T','C','A',0}, 10039880, 796 }, /* Turks and Caicos Islands */
+    { 351, {'V','G',0}, {'V','G','B',0}, 10039880,  92 }, /* Virgin Islands, British */
+    { 352, {'W','F',0}, {'W','L','F',0}, 26286, 876 }, /* Wallis and Futuna */
+    { 742, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Africa */
+    { 2129, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Asia */
+    { 10541, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Europe */
+    { 15126, {'I','M',0}, {'I','M','N',0}, 10039882, 833 }, /* Man, Isle of */
+    { 19618, {'M','K',0}, {'M','K','D',0}, 47610, 807 }, /* Macedonia, Former Yugoslav Republic of */
+    { 20900, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Melanesia */
+    { 21206, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Micronesia */
+    { 21242, {'X','X',0}, {'X','X',0}, 161832256 }, /* Midway Islands */
+    { 23581, {'X','X',0}, {'X','X',0}, 10026358, 0, LOCATION_REGION }, /* Northern America */
+    { 26286, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Polynesia */
+    { 27082, {'X','X',0}, {'X','X',0}, 161832257, 0, LOCATION_REGION }, /* Central America */
+    { 27114, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Oceania */
+    { 30967, {'S','X',0}, {'S','X','M',0}, 10039880, 534 }, /* Sint Maarten (Dutch part) */
+    { 31396, {'X','X',0}, {'X','X',0}, 161832257, 0, LOCATION_REGION }, /* South America */
+    { 31706, {'M','F',0}, {'M','A','F',0}, 10039880, 663 }, /* Saint Martin (French part) */
+    { 39070, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* World */
+    { 42483, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Western Africa */
+    { 42484, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Middle Africa */
+    { 42487, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Northern Africa */
+    { 47590, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Central Asia */
+    { 47599, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* South-Eastern Asia */
+    { 47600, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Eastern Asia */
+    { 47603, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Eastern Africa */
+    { 47609, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Eastern Europe */
+    { 47610, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Southern Europe */
+    { 47611, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Middle East */
+    { 47614, {'X','X',0}, {'X','X',0}, 2129, 0, LOCATION_REGION }, /* Southern Asia */
+    { 7299303, {'T','L',0}, {'T','L','S',0}, 47599, 626 }, /* Democratic Republic of Timor-Leste */
+    { 10026358, {'X','X',0}, {'X','X',0}, 39070, 0, LOCATION_REGION }, /* Americas */
+    { 10028789, {'A','X',0}, {'A','L','A',0}, 10039882, 248 }, /* Åland Islands */
+    { 10039880, {'X','X',0}, {'X','X',0}, 161832257, 0, LOCATION_REGION }, /* Caribbean */
+    { 10039882, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Northern Europe */
+    { 10039883, {'X','X',0}, {'X','X',0}, 742, 0, LOCATION_REGION }, /* Southern Africa */
+    { 10210824, {'X','X',0}, {'X','X',0}, 10541, 0, LOCATION_REGION }, /* Western Europe */
+    { 10210825, {'X','X',0}, {'X','X',0}, 27114, 0, LOCATION_REGION }, /* Australia and New Zealand */
+    { 161832015, {'B','L',0}, {'B','L','M',0}, 10039880, 652 }, /* Saint Barthélemy */
+    { 161832256, {'U','M',0}, {'U','M','I',0}, 27114, 581 }, /* U.S. Minor Outlying Islands */
+    { 161832257, {'X','X',0}, {'X','X',0}, 10026358, 0, LOCATION_REGION }, /* Latin America and the Caribbean */
+};
+
 /******************************************************************************
  *           EnumLanguageGroupLocalesA    (KERNEL32.@)
  *
@@ -2440,67 +2734,53 @@ EnumSystemCodePagesA (
 
     return NLS_EnumSystemCodePages(lpCodePageEnumProc ? &procs : NULL);
 }
+
 /******************************************************************************
  *           EnumSystemGeoID    (KERNEL32.@)
  *
  * Call a users function for every location available on the system.
  *
  * PARAMS
- *  geoclass     [I] Type of information desired (SYSGEOTYPE enum from "winnls.h")
- *  reserved     [I] Reserved, set to 0
- *  pGeoEnumProc [I] Callback function to call for each location
+ *  geoclass   [I] Type of information desired (SYSGEOTYPE enum from "winnls.h")
+ *  parent     [I] GEOID for the parent
+ *  enumproc   [I] Callback function to call for each location
  *
  * RETURNS
  *  Success: TRUE.
  *  Failure: FALSE. Use GetLastError() to determine the cause.
  */
-BOOL WINAPI EnumSystemGeoID(GEOCLASS geoclass, GEOID reserved, GEO_ENUMPROC pGeoEnumProc)
+BOOL WINAPI EnumSystemGeoID(GEOCLASS geoclass, GEOID parent, GEO_ENUMPROC enumproc)
 {
-    static const WCHAR szCountryCodeValueName[] = {
-      'C','o','u','n','t','r','y','C','o','d','e','\0'
-    };
-    WCHAR szNumber[10];
-    HANDLE hKey;
-    ULONG ulIndex = 0;
+    INT i;
 
-    TRACE("(0x%08X,0x%08X,%p)\n", geoclass, reserved, pGeoEnumProc);
+    TRACE("(%d, %d, %p)\n", geoclass, parent, enumproc);
 
-    if (geoclass != GEOCLASS_NATION || reserved || !pGeoEnumProc)
-    {
+    if (!enumproc) {
         SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
 
-    hKey = NLS_RegOpenKey( 0, szCountryListName );
+    if (geoclass != GEOCLASS_NATION && geoclass != GEOCLASS_REGION) {
+        SetLastError(ERROR_INVALID_FLAGS);
+        return FALSE;
+    }
 
-    while (NLS_RegEnumSubKey( hKey, ulIndex, szNumber, sizeof(szNumber) ))
-    {
-        BOOL bContinue = TRUE;
-        DWORD dwGeoId;
-        HANDLE hSubKey = NLS_RegOpenKey( hKey, szNumber );
+    for (i = 0; i < sizeof(geoinfodata)/sizeof(struct geoinfo_t); i++) {
+        const struct geoinfo_t *ptr = &geoinfodata[i];
 
-        if (hSubKey)
-        {
-            if (NLS_RegGetDword( hSubKey, szCountryCodeValueName, &dwGeoId ))
-            {
-                TRACE("Got geoid %d\n", dwGeoId);
+        if (geoclass == GEOCLASS_NATION && (ptr->kind == LOCATION_REGION))
+            continue;
 
-                if (!pGeoEnumProc( dwGeoId ))
-                    bContinue = FALSE;
-            }
+        if (geoclass == GEOCLASS_REGION && (ptr->kind == LOCATION_NATION))
+            continue;
 
-            NtClose( hSubKey );
-        }
-
-        if (!bContinue)
-            break;
+        if (parent && ptr->parent != parent)
+            continue;
 
-        ulIndex++;
+        if (!enumproc(ptr->id))
+            return TRUE;
     }
 
-    if (hKey)
-        NtClose( hKey );
-
     return TRUE;
 }
 
@@ -2762,73 +3042,130 @@ NLS_GetGeoFriendlyName(GEOID Location, LPWSTR szFriendlyName, int cchData)
     return Ret;
 }
 
-/*
- * @implemented
+static const struct geoinfo_t *get_geoinfo_dataptr(GEOID geoid)
+{
+    int min, max;
+
+    min = 0;
+    max = sizeof(geoinfodata)/sizeof(struct geoinfo_t)-1;
+
+    while (min <= max) {
+        const struct geoinfo_t *ptr;
+        int n = (min+max)/2;
+
+        ptr = &geoinfodata[n];
+        if (geoid == ptr->id)
+            /* we don't need empty entry */
+            return *ptr->iso2W ? ptr : NULL;
+
+        if (ptr->id > geoid)
+            max = n-1;
+        else
+            min = n+1;
+    }
+
+    return NULL;
+}
+
+/******************************************************************************
+ *           GetGeoInfoW (KERNEL32.@)
  */
-INT WINAPI GetGeoInfoW(GEOID GeoId, GEOTYPE GeoType, LPWSTR lpGeoData, 
-                int cchData, LANGID LangId)
+INT WINAPI GetGeoInfoW(GEOID geoid, GEOTYPE geotype, LPWSTR data, int data_len, LANGID lang)
 {
-       TRACE("%d %d %p %d %d\n", GeoId, GeoType, lpGeoData, cchData, LangId);
+    const struct geoinfo_t *ptr;
+    const WCHAR *str = NULL;
+    WCHAR buffW[12];
+    LONG val = 0;
+    INT len;
+
+    TRACE("%d %d %p %d %d\n", geoid, geotype, data, data_len, lang);
+
+    if (!(ptr = get_geoinfo_dataptr(geoid))) {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return 0;
+    }
 
-    switch (GeoType)
+    switch (geotype) {
+    case GEO_FRIENDLYNAME:
     {
-        case GEO_FRIENDLYNAME:
-        {
-            return NLS_GetGeoFriendlyName(GeoId, lpGeoData, cchData);
-        }
-        case GEO_TIMEZONES:
-        case GEO_NATION:
-        case GEO_LATITUDE:
-        case GEO_LONGITUDE:
-        case GEO_ISO2:
-        case GEO_ISO3:
-        case GEO_RFC1766:
-        case GEO_LCID:
-        case GEO_OFFICIALNAME:
-        case GEO_OFFICIALLANGUAGES:
-            FIXME("%d %d %p %d %d\n", GeoId, GeoType, lpGeoData, cchData, LangId);
-            SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+        return NLS_GetGeoFriendlyName(geoid, data, data_len);
+    }
+    case GEO_NATION:
+        val = geoid;
+        break;
+    case GEO_ISO_UN_NUMBER:
+        val = ptr->uncode;
+        break;
+    case GEO_PARENT:
+        val = ptr->parent;
         break;
+    case GEO_ISO2:
+    case GEO_ISO3:
+    {
+        str = geotype == GEO_ISO2 ? ptr->iso2W : ptr->iso3W;
+        break;
+    }
+    case GEO_RFC1766:
+    case GEO_LCID:
+    case GEO_OFFICIALNAME:
+    case GEO_TIMEZONES:
+    case GEO_OFFICIALLANGUAGES:
+    case GEO_LATITUDE:
+    case GEO_LONGITUDE:
+        FIXME("type %d is not supported\n", geotype);
+        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+        return 0;
+    default:
+        WARN("unrecognized type %d\n", geotype);
+        SetLastError(ERROR_INVALID_FLAGS);
+        return 0;
+    }
+
+    if (val) {
+        static const WCHAR fmtW[] = {'%','d',0};
+        sprintfW(buffW, fmtW, val);
+        str = buffW;
     }
 
-    return 0;
+    len = strlenW(str) + 1;
+    if (!data || !data_len)
+        return len;
+
+    memcpy(data, str, min(len, data_len)*sizeof(WCHAR));
+    if (data_len < len)
+        SetLastError(ERROR_INSUFFICIENT_BUFFER);
+    return data_len < len ? 0 : len;
 }
 
-/*
- * @implemented
+/******************************************************************************
+ *           GetGeoInfoA (KERNEL32.@)
  */
-INT WINAPI GetGeoInfoA(GEOID GeoId, GEOTYPE GeoType, LPSTR lpGeoData, 
-                int cchData, LANGID LangId)
+INT WINAPI GetGeoInfoA(GEOID geoid, GEOTYPE geotype, LPSTR data, int data_len, LANGID lang)
 {
-       WCHAR szBuffer[MAX_PATH];
-    char szBufferA[sizeof(szBuffer)/sizeof(WCHAR)];
-    int Ret;
+    WCHAR *buffW;
+    INT len;
 
-    TRACE("%d %d %p %d %d\n", GeoId, GeoType, lpGeoData, cchData, LangId);
+    TRACE("%d %d %p %d %d\n", geoid, geotype, data, data_len, lang);
 
-    switch (GeoType)
-    {
-        case GEO_FRIENDLYNAME:
-        {
-            Ret = NLS_GetGeoFriendlyName(GeoId, szBuffer, cchData);
-            WideCharToMultiByte(CP_ACP, 0, szBuffer, -1, szBufferA, sizeof(szBufferA), 0, 0);
-            strcpy(lpGeoData, szBufferA);
-            return Ret;
-        }
-        case GEO_TIMEZONES:
-        case GEO_NATION:
-        case GEO_LATITUDE:
-        case GEO_LONGITUDE:
-        case GEO_ISO2:
-        case GEO_ISO3:
-        case GEO_RFC1766:
-        case GEO_LCID:
-        case GEO_OFFICIALNAME:
-        case GEO_OFFICIALLANGUAGES:
-            FIXME("%d %d %p %d %d\n", GeoId, GeoType, lpGeoData, cchData, LangId);
-            SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-        break;
+    len = GetGeoInfoW(geoid, geotype, NULL, 0, lang);
+    if (!len)
+        return 0;
+
+    buffW = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
+    if (!buffW)
+        return 0;
+
+    GetGeoInfoW(geoid, geotype, buffW, len, lang);
+    len = WideCharToMultiByte(CP_ACP, 0, buffW, -1, NULL, 0, NULL, NULL);
+    if (!data || !data_len) {
+        HeapFree(GetProcessHeap(), 0, buffW);
+        return len;
     }
 
-    return 0;
+    len = WideCharToMultiByte(CP_ACP, 0, buffW, -1, data, data_len, NULL, NULL);
+    HeapFree(GetProcessHeap(), 0, buffW);
+
+    if (data_len < len)
+        SetLastError(ERROR_INSUFFICIENT_BUFFER);
+    return data_len < len ? 0 : len;
 }
index 60c92fe..cae8b66 100644 (file)
@@ -22,6 +22,7 @@
 #include "setupapi_private.h"
 
 #include <wingdi.h>
+#include <shellapi.h>
 
 /* Unicode constants */
 static const WCHAR BackSlash[] = {'\\',0};
@@ -76,6 +77,7 @@ static const INSTALL_PARAMS_DATA InstallParamsData[] = {
 };
 #undef ADD_PARAM_HANDLER
 
+#define UNKNOWN_ICON_INDEX 18
 
 /***********************************************************************
  *             SetupDiDestroyClassImageList(SETUPAPI.@)
@@ -330,9 +332,6 @@ cleanup:
     return rc;
 }
 
-/***********************************************************************
- *             SetupDiGetClassImageIndex (SETUPAPI.@)
- */
 static BOOL
 SETUP_GetIconIndex(
     IN HKEY hClassKey,
@@ -378,6 +377,9 @@ cleanup:
     return ret;
 }
 
+/***********************************************************************
+ *             SetupDiGetClassImageIndex (SETUPAPI.@)
+ */
 BOOL WINAPI
 SetupDiGetClassImageIndex(
     IN PSP_CLASSIMAGELIST_DATA ClassImageListData,
@@ -458,6 +460,102 @@ SetupDiGetClassImageListExA(
     return ret;
 }
 
+static BOOL WINAPI 
+SETUP_GetClassIconInfo(IN CONST GUID *ClassGuid, OUT PINT OutIndex, OUT LPWSTR *OutDllName)
+{
+    LPWSTR Buffer = NULL;
+    INT iconIndex = -UNKNOWN_ICON_INDEX;
+    HKEY hKey = INVALID_HANDLE_VALUE;
+    BOOL ret = FALSE;
+
+    if (ClassGuid)
+    {
+        hKey = SetupDiOpenClassRegKey(ClassGuid, KEY_QUERY_VALUE);
+        if (hKey != INVALID_HANDLE_VALUE)
+        {
+            SETUP_GetIconIndex(hKey, &iconIndex);
+        }
+    }
+
+    if (iconIndex > 0)
+    {
+        /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
+        PWCHAR Comma;
+        LONG rc;
+        DWORD dwRegType, dwLength;
+        rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength);
+        if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
+        {
+            Buffer = MyMalloc(dwLength + sizeof(WCHAR));
+            if (Buffer == NULL)
+            {
+                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                goto cleanup;
+            }
+            rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)Buffer, &dwLength);
+            if (rc != ERROR_SUCCESS)
+            {
+                SetLastError(rc);
+                goto cleanup;
+            }
+            /* make sure the returned buffer is NULL-terminated */
+            Buffer[dwLength / sizeof(WCHAR)] = 0;
+        }
+        else if
+            (ERROR_SUCCESS == (rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength))
+            && dwRegType == REG_SZ)
+        {
+            Buffer = MyMalloc(dwLength + sizeof(WCHAR));
+            if (Buffer == NULL)
+            {
+                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                goto cleanup;
+            }
+            rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)Buffer, &dwLength);
+            if (rc != ERROR_SUCCESS)
+            {
+                SetLastError(rc);
+                goto cleanup;
+            }
+            /* make sure the returned buffer is NULL-terminated */
+            Buffer[dwLength / sizeof(WCHAR)] = 0;
+        }
+        else
+        {
+            /* Unable to find where to load the icon */
+            SetLastError(ERROR_FILE_NOT_FOUND);
+            goto cleanup;
+        }
+        Comma = strchrW(Buffer, ',');
+        if (!Comma)
+        {
+            SetLastError(ERROR_GEN_FAILURE);
+            goto cleanup;
+        }
+        *Comma = '\0';
+        *OutDllName = Buffer;
+    }
+    else
+    {
+        /* Look up icon in setupapi.dll */
+        iconIndex = -iconIndex;
+        *OutDllName = NULL;
+    }
+
+    *OutIndex = iconIndex;
+    ret = TRUE;
+
+    TRACE("Icon index %d, dll name %s\n", iconIndex, debugstr_w(*OutDllName ? *OutDllName : SetupapiDll));
+
+cleanup:
+
+    if (hKey != INVALID_HANDLE_VALUE)
+        RegCloseKey(hKey);
+
+    return ret;
+}
+
+
 /***********************************************************************
  *             SetupDiGetClassImageListExW(SETUPAPI.@)
  */
@@ -570,24 +668,32 @@ SetupDiGetClassImageListExW(
         for (i = 0; i < list->NumberOfGuids; i++)
         {
             INT miniIconIndex;
+            LPWSTR DllName = NULL;
 
-            ret = SetupDiLoadClassIcon(
-                &list->Guids[i],
-                NULL,
-                &miniIconIndex);
-            if (ret)
+            if (SETUP_GetClassIconInfo(&list->Guids[i], &miniIconIndex, &DllName))
             {
-                hIcon = LoadImage(hInstance, MAKEINTRESOURCE(miniIconIndex), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
-                if (hIcon)
+                if (DllName && ExtractIconExW(DllName, -miniIconIndex, NULL, &hIcon, 1) == 1)
                 {
                     list->IconIndexes[i] = ImageList_AddIcon(ClassImageListData->ImageList, hIcon);
-                    DestroyIcon(hIcon);
                 }
+                else if(!DllName)
+                {
+                    hIcon = LoadImage(hInstance, MAKEINTRESOURCE(miniIconIndex), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
+                    list->IconIndexes[i] = ImageList_AddIcon(ClassImageListData->ImageList, hIcon);
+                }
+
+                if(hIcon)
+                    DestroyIcon(hIcon);
                 else
                     list->IconIndexes[i] = -1;
+
+                if(DllName)
+                    MyFree(DllName);
             }
             else
+            {
                 list->IconIndexes[i] = -1; /* Special value to indicate that the icon is unavailable */
+            }
         }
 
         /* Finally, add the overlay icons to the image list */
@@ -660,105 +766,43 @@ SetupDiLoadClassIcon(
     OUT HICON *LargeIcon OPTIONAL,
     OUT PINT MiniIconIndex OPTIONAL)
 {
-    LPWSTR Buffer = NULL;
-    LPCWSTR DllName;
-    INT iconIndex = -18;
-    HKEY hKey = INVALID_HANDLE_VALUE;
-
+    INT iconIndex = 0;
+    LPWSTR DllName = NULL;
     BOOL ret = FALSE;
+    HICON hIcon = NULL;
 
-    if (ClassGuid)
+    if (LargeIcon)
     {
-        hKey = SetupDiOpenClassRegKey(ClassGuid, KEY_QUERY_VALUE);
-        if (hKey != INVALID_HANDLE_VALUE)
-            SETUP_GetIconIndex(hKey, &iconIndex);
-    }
+        if(!SETUP_GetClassIconInfo(ClassGuid, &iconIndex, &DllName))
+            return FALSE;
 
-    if (iconIndex > 0)
-    {
-        /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
-        PWCHAR Comma;
-        LONG rc;
-        DWORD dwRegType, dwLength;
-        rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength);
-        if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
-        {
-            Buffer = MyMalloc(dwLength + sizeof(WCHAR));
-            if (Buffer == NULL)
-            {
-                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-                goto cleanup;
-            }
-            rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)Buffer, &dwLength);
-            if (rc != ERROR_SUCCESS)
-            {
-                SetLastError(rc);
-                goto cleanup;
-            }
-            /* make sure the returned buffer is NULL-terminated */
-            Buffer[dwLength / sizeof(WCHAR)] = 0;
-        }
-        else if
-            (ERROR_SUCCESS == (rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength))
-            && dwRegType == REG_SZ)
+        if (DllName && ExtractIconExW(DllName, -iconIndex, &hIcon, NULL, 1) == 1 && hIcon != NULL)
         {
-            Buffer = MyMalloc(dwLength + sizeof(WCHAR));
-            if (Buffer == NULL)
-            {
-                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-                goto cleanup;
-            }
-            rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)Buffer, &dwLength);
-            if (rc != ERROR_SUCCESS)
-            {
-                SetLastError(rc);
-                goto cleanup;
-            }
-            /* make sure the returned buffer is NULL-terminated */
-            Buffer[dwLength / sizeof(WCHAR)] = 0;
+            ret = TRUE;
         }
         else
         {
-            /* Unable to find where to load the icon */
-            SetLastError(ERROR_FILE_NOT_FOUND);
-            goto cleanup;
-        }
-        Comma = strchrW(Buffer, ',');
-        if (!Comma)
-        {
-            SetLastError(ERROR_GEN_FAILURE);
-            goto cleanup;
-        }
-        *Comma = '\0';
-        DllName = Buffer;
-    }
-    else
-    {
-        /* Look up icon in setupapi.dll */
-        DllName = SetupapiDll;
-        iconIndex = -iconIndex;
-    }
+            /* load the default unknown device icon if ExtractIcon failed */
+            if(DllName)
+                iconIndex = UNKNOWN_ICON_INDEX;
 
-    TRACE("Icon index %d, dll name %s\n", iconIndex, debugstr_w(DllName));
-    if (LargeIcon)
-    {
-        *LargeIcon = LoadImage(hInstance, MAKEINTRESOURCE(iconIndex), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
-        if (!*LargeIcon)
-        {
-            SetLastError(ERROR_INVALID_INDEX);
-            goto cleanup;
+            hIcon = LoadImage(hInstance, MAKEINTRESOURCE(iconIndex), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
+
+            if(!LargeIcon)
+                goto cleanup;
         }
     }
+
     if (MiniIconIndex)
         *MiniIconIndex = iconIndex;
+
     ret = TRUE;
+    *LargeIcon = hIcon;
 
 cleanup:
-    if (hKey != INVALID_HANDLE_VALUE)
-        RegCloseKey(hKey);
 
-    if (Buffer != NULL)
-        MyFree(Buffer);
+    if(DllName)
+        MyFree(DllName);
 
     TRACE("Returning %d\n", ret);
     return ret;
index 1ee48fb..3d550cc 100644 (file)
@@ -918,7 +918,7 @@ getnameinfo(const struct sockaddr FAR *sa,
     WCHAR ServiceBuffer[17];
     DWORD HostLength = 0, ServLength = 0;
     PWCHAR ServiceString = NULL, HostString = NULL;
-    DPRINT("getaddrinfo: %p, %p, %p, %lx\n", host, serv, sa, salen);
+    DPRINT("getnameinfo: %p, %p, %p, %lx\n", host, serv, sa, salen);
 
     /* Check for WSAStartup */
     if ((ErrorCode = WsQuickProlog()) != ERROR_SUCCESS) return ErrorCode;
index 007c3c5..3ad1a9f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
- * FILE:             drivers/fs/vfat/close.c
+ * FILE:             drivers/filesystems/fastfat/close.c
  * PURPOSE:          VFAT Filesystem
  * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
  */
@@ -51,7 +51,7 @@ VfatCloseFile(
         {
             if (pFcb->Flags & FCB_DELETE_PENDING)
             {
-                VfatDelEntry(DeviceExt, pFcb);
+                VfatDelEntry(DeviceExt, pFcb, NULL);
 
                 FsRtlNotifyFullReportChange(DeviceExt->NotifySync,
                                             &(DeviceExt->NotifyList),
index 468b902..9352d1c 100644 (file)
  */
 /*
  * PROJECT:          ReactOS kernel
- * FILE:             drivers/fs/vfat/create.c
+ * FILE:             drivers/filesystems/fastfat/create.c
  * PURPOSE:          VFAT Filesystem
  * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
+ *                   Pierre Schweitzer (pierre@reactos.org)
  */
 
 /* INCLUDES *****************************************************************/
@@ -352,7 +353,6 @@ VfatOpenFile(
     PUNICODE_STRING PathNameU,
     PFILE_OBJECT FileObject,
     ULONG RequestedDisposition,
-    BOOLEAN OpenTargetDir,
     PVFATFCB *ParentFcb)
 {
     PVFATFCB Fcb;
@@ -404,13 +404,6 @@ VfatOpenFile(
         return  Status;
     }
 
-    /* In case we're to open target, just check whether file exist, but don't open it */
-    if (OpenTargetDir)
-    {
-        vfatReleaseFCB(DeviceExt, Fcb);
-        return STATUS_OBJECT_NAME_COLLISION;
-    }
-
     if (Fcb->Flags & FCB_DELETE_PENDING)
     {
         vfatReleaseFCB(DeviceExt, Fcb);
@@ -462,11 +455,8 @@ VfatCreateFile(
     RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
     RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
     PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE;
-#if 0
     OpenTargetDir = (Stack->Flags & SL_OPEN_TARGET_DIRECTORY) ? TRUE : FALSE;
-#else
-    OpenTargetDir = FALSE;
-#endif
+
     FileObject = Stack->FileObject;
     DeviceExt = DeviceObject->DeviceExtension;
 
@@ -558,14 +548,22 @@ VfatCreateFile(
     }
 
     /* Try opening the file. */
-    Status = VfatOpenFile(DeviceExt, &PathNameU, FileObject, RequestedDisposition, OpenTargetDir, &ParentFcb);
-
-    if (OpenTargetDir)
+    if (!OpenTargetDir)
     {
+        Status = VfatOpenFile(DeviceExt, &PathNameU, FileObject, RequestedDisposition, &ParentFcb);
+    }
+    else
+    {
+        PVFATFCB TargetFcb;
         LONG idx, FileNameLen;
 
-        if (Status == STATUS_OBJECT_NAME_COLLISION)
+        ParentFcb = (FileObject->RelatedFileObject != NULL) ? FileObject->RelatedFileObject->FsContext : NULL;
+        Status = vfatGetFCBForFile(DeviceExt, &ParentFcb, &TargetFcb, &PathNameU);
+
+        if (Status == STATUS_SUCCESS)
         {
+            ParentFcb->RefCount++;
+            vfatReleaseFCB(DeviceExt, TargetFcb);
             Irp->IoStatus.Information = FILE_EXISTS;
         }
         else
@@ -593,10 +591,6 @@ VfatCreateFile(
             /* We don't want to include / in the name */
             FileNameLen = PathNameU.Length - ((idx + 1) * sizeof(WCHAR));
 
-            /* Try to open parent */
-            PathNameU.Length -= (PathNameU.Length - idx * sizeof(WCHAR));
-            Status = VfatOpenFile(DeviceExt, &PathNameU, FileObject, RequestedDisposition, FALSE, &ParentFcb);
-
             /* Update FO just to keep file name */
             /* Skip first slash */
             ++idx;
@@ -608,32 +602,47 @@ VfatCreateFile(
             /* This is a relative open and we have only the filename, so open the parent directory
              * It is in RelatedFileObject
              */
-            BOOLEAN Chomp = FALSE;
-            PFILE_OBJECT RelatedFileObject = FileObject->RelatedFileObject;
+            ASSERT(FileObject->RelatedFileObject != NULL);
 
-            DPRINT("%wZ\n", &PathNameU);
+            /* No need to modify the FO, it already has the name */
+        }
 
-            ASSERT(RelatedFileObject != NULL);
+        /* We're done with opening! */
+        if (ParentFcb != NULL)
+        {
+            Status = vfatAttachFCBToFileObject(DeviceExt, ParentFcb, FileObject);
+        }
 
-            DPRINT("Relative opening\n");
-            DPRINT("FileObject->RelatedFileObject->FileName: %wZ\n", &RelatedFileObject->FileName);
+        if (NT_SUCCESS(Status))
+        {
+            pFcb = FileObject->FsContext;
 
-            /* VfatOpenFile() doesn't like our name ends with \, so chomp it if there's one */
-            if (RelatedFileObject->FileName.Buffer[RelatedFileObject->FileName.Length / sizeof(WCHAR) - 1] == L'\\')
+            if (pFcb->OpenHandleCount == 0)
             {
-                Chomp = TRUE;
-                RelatedFileObject->FileName.Length -= sizeof(WCHAR);
+                IoSetShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
+                                 Stack->Parameters.Create.ShareAccess,
+                                 FileObject,
+                                 &pFcb->FCBShareAccess);
+            }
+            else
+            {
+                Status = IoCheckShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
+                                            Stack->Parameters.Create.ShareAccess,
+                                            FileObject,
+                                            &pFcb->FCBShareAccess,
+                                            FALSE);
+                if (!NT_SUCCESS(Status))
+                {
+                    VfatCloseFile(DeviceExt, FileObject);
+                    return Status;
+                }
             }
 
-            /* Tricky part - fake our FO. It's NOT relative, we want to open the complete file path */
-            FileObject->RelatedFileObject = NULL;
-            Status = VfatOpenFile(DeviceExt, &RelatedFileObject->FileName, FileObject, RequestedDisposition, FALSE, &ParentFcb);
-
-            /* We're done opening, restore what we broke */
-            FileObject->RelatedFileObject = RelatedFileObject;
-            if (Chomp) RelatedFileObject->FileName.Length += sizeof(WCHAR);
-
-            /* No need to modify the FO, it already has the name */
+            pFcb->OpenHandleCount++;
+        }
+        else if (ParentFcb != NULL)
+        {
+            vfatReleaseFCB(DeviceExt, ParentFcb);
         }
 
         return Status;
@@ -673,7 +682,7 @@ VfatCreateFile(
                 Attributes |= FILE_ATTRIBUTE_ARCHIVE;
             vfatSplitPathName(&PathNameU, NULL, &FileNameU);
             Status = VfatAddEntry(DeviceExt, &FileNameU, &pFcb, ParentFcb, RequestedOptions,
-                                  (UCHAR)(Attributes & FILE_ATTRIBUTE_VALID_FLAGS));
+                                  (UCHAR)(Attributes & FILE_ATTRIBUTE_VALID_FLAGS), NULL);
             vfatReleaseFCB(DeviceExt, ParentFcb);
             if (NT_SUCCESS(Status))
             {
index 1444665..21b0e69 100644 (file)
@@ -1,8 +1,11 @@
 /*
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
- * FILE:             drivers/fs/vfat/dirwr.c
+ * FILE:             drivers/filesystems/fastfat/dirwr.c
  * PURPOSE:          VFAT Filesystem : write in directory
+ * PROGRAMMER:       Rex Jolliff (rex@lvcablemodem.com)
+ *                   Herve Poussineau (reactos@poussine.freesurf.fr)
+ *                   Pierre Schweitzer (pierre@reactos.org)
  *
  */
 
@@ -66,6 +69,70 @@ VfatUpdateEntry(
     }
 }
 
+/*
+ * rename an existing FAT entry
+ */
+NTSTATUS
+vfatRenameEntry(
+    IN PDEVICE_EXTENSION DeviceExt,
+    IN PVFATFCB pFcb,
+    IN PUNICODE_STRING FileName,
+    IN BOOLEAN CaseChangeOnly)
+{
+    OEM_STRING NameA;
+    ULONG StartIndex;
+    PVOID Context = NULL;
+    LARGE_INTEGER Offset;
+    PFATX_DIR_ENTRY pDirEntry;
+    UNICODE_STRING ShortName;
+    NTSTATUS Status;
+
+    DPRINT("vfatRenameEntry(%p, %p, %wZ, %d)\n", DeviceExt, pFcb, FileName, CaseChangeOnly);
+
+    if (pFcb->Flags & FCB_IS_FATX_ENTRY)
+    {
+        /* Open associated dir entry */
+        StartIndex = pFcb->startIndex;
+        Offset.u.HighPart = 0;
+        Offset.u.LowPart = (StartIndex * sizeof(FATX_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
+        if (!CcPinRead(pFcb->parentFcb->FileObject, &Offset, sizeof(FATX_DIR_ENTRY), TRUE,
+                       &Context, (PVOID*)&pDirEntry))
+        {
+            DPRINT1("CcPinRead(Offset %x:%x, Length %d) failed\n", Offset.u.HighPart, Offset.u.LowPart, PAGE_SIZE);
+            return STATUS_UNSUCCESSFUL;
+        }
+
+        pDirEntry = &pDirEntry[StartIndex % (PAGE_SIZE / sizeof(FATX_DIR_ENTRY))];
+
+        /* Set file name */
+        NameA.Buffer = (PCHAR)pDirEntry->Filename;
+        NameA.Length = 0;
+        NameA.MaximumLength = 42;
+        RtlUnicodeStringToOemString(&NameA, FileName, FALSE);
+        pDirEntry->FilenameLength = (unsigned char)NameA.Length;
+
+        CcSetDirtyPinnedData(Context, NULL);
+        CcUnpinData(Context);
+
+        /* Update FCB */
+        ShortName.Length = 0;
+        ShortName.MaximumLength = 0;
+        ShortName.Buffer = NULL;
+        Status = vfatUpdateFCB(DeviceExt, pFcb, FileName, &ShortName, pFcb->parentFcb);
+        if (NT_SUCCESS(Status))
+        {
+            CcPurgeCacheSection(&pFcb->parentFcb->SectionObjectPointers, NULL, 0, FALSE);
+        }
+
+        return Status;
+    }
+    else
+    {
+        /* This we cannot handle properly, move file - would likely need love */
+        return VfatMoveEntry(DeviceExt, pFcb, FileName, pFcb->parentFcb);
+    }
+}
+
 /*
  * try to find contiguous entries frees in directory,
  * extend a directory if is neccesary
@@ -200,7 +267,8 @@ FATAddEntry(
     IN PVFATFCB* Fcb,
     IN PVFATFCB ParentFcb,
     IN ULONG RequestedOptions,
-    IN UCHAR ReqAttr)
+    IN UCHAR ReqAttr,
+    IN PVFAT_MOVE_CONTEXT MoveContext)
 {
     PVOID Context = NULL;
     PFAT_DIR_ENTRY pFatEntry;
@@ -385,6 +453,13 @@ FATAddEntry(
     DirContext.DirEntry.Fat.UpdateDate = DirContext.DirEntry.Fat.CreationDate;
     DirContext.DirEntry.Fat.UpdateTime = DirContext.DirEntry.Fat.CreationTime;
     DirContext.DirEntry.Fat.AccessDate = DirContext.DirEntry.Fat.CreationDate;
+    /* If it's moving, preserve creation time and file size */
+    if (MoveContext != NULL)
+    {
+        DirContext.DirEntry.Fat.CreationDate = MoveContext->CreationDate;
+        DirContext.DirEntry.Fat.CreationTime = MoveContext->CreationTime;
+        DirContext.DirEntry.Fat.FileSize = MoveContext->FileSize;
+    }
 
     if (needLong)
     {
@@ -423,17 +498,36 @@ FATAddEntry(
     DirContext.DirIndex = DirContext.StartIndex + nbSlots - 1;
     if (RequestedOptions & FILE_DIRECTORY_FILE)
     {
-        CurrentCluster = 0;
-        Status = NextCluster(DeviceExt, 0, &CurrentCluster, TRUE);
-        if (CurrentCluster == 0xffffffff || !NT_SUCCESS(Status))
+        /* If we aren't moving, use next */
+        if (MoveContext == NULL)
         {
-            ExFreePoolWithTag(Buffer, TAG_VFAT);
-            if (!NT_SUCCESS(Status))
+            CurrentCluster = 0;
+            Status = NextCluster(DeviceExt, 0, &CurrentCluster, TRUE);
+            if (CurrentCluster == 0xffffffff || !NT_SUCCESS(Status))
             {
-                return Status;
+                ExFreePoolWithTag(Buffer, TAG_VFAT);
+                if (!NT_SUCCESS(Status))
+                {
+                    return Status;
+                }
+                return STATUS_DISK_FULL;
             }
-            return STATUS_DISK_FULL;
         }
+        else
+        {
+            CurrentCluster = MoveContext->FirstCluster;
+        }
+
+        if (DeviceExt->FatInfo.FatType == FAT32)
+        {
+            DirContext.DirEntry.Fat.FirstClusterHigh = (unsigned short)(CurrentCluster >> 16);
+        }
+        DirContext.DirEntry.Fat.FirstCluster = (unsigned short)CurrentCluster;
+    }
+    else if (MoveContext != NULL)
+    {
+        CurrentCluster = MoveContext->FirstCluster;
+
         if (DeviceExt->FatInfo.FatType == FAT32)
         {
             DirContext.DirEntry.Fat.FirstClusterHigh = (unsigned short)(CurrentCluster >> 16);
@@ -491,7 +585,17 @@ FATAddEntry(
     CcSetDirtyPinnedData(Context, NULL);
     CcUnpinData(Context);
 
-    Status = vfatMakeFCBFromDirEntry(DeviceExt, ParentFcb, &DirContext, Fcb);
+    if (MoveContext != NULL)
+    {
+        /* We're modifying an existing FCB - likely rename/move */
+        Status = vfatUpdateFCB(DeviceExt, *Fcb, &DirContext.LongNameU, &DirContext.ShortNameU, ParentFcb);
+        (*Fcb)->dirIndex = DirContext.DirIndex;
+        (*Fcb)->startIndex = DirContext.StartIndex;
+    }
+    else
+    {
+        Status = vfatMakeFCBFromDirEntry(DeviceExt, ParentFcb, &DirContext, Fcb);
+    }
     if (!NT_SUCCESS(Status))
     {
         ExFreePoolWithTag(Buffer, TAG_VFAT);
@@ -510,13 +614,17 @@ FATAddEntry(
             ExFreePoolWithTag(Buffer, TAG_VFAT);
             return STATUS_UNSUCCESSFUL;
         }
-        /* clear the new directory cluster */
-        RtlZeroMemory(pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
-        /* create '.' and '..' */
-        RtlCopyMemory(&pFatEntry[0].Attrib, &DirContext.DirEntry.Fat.Attrib, sizeof(FAT_DIR_ENTRY) - 11);
-        RtlCopyMemory(pFatEntry[0].ShortName, ".          ", 11);
-        RtlCopyMemory(&pFatEntry[1].Attrib, &DirContext.DirEntry.Fat.Attrib, sizeof(FAT_DIR_ENTRY) - 11);
-        RtlCopyMemory(pFatEntry[1].ShortName, "..         ", 11);
+        /* clear the new directory cluster if not moving */
+        if (MoveContext == NULL)
+        {
+            RtlZeroMemory(pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
+            /* create '.' and '..' */
+            RtlCopyMemory(&pFatEntry[0].Attrib, &DirContext.DirEntry.Fat.Attrib, sizeof(FAT_DIR_ENTRY) - 11);
+            RtlCopyMemory(pFatEntry[0].ShortName, ".          ", 11);
+            RtlCopyMemory(&pFatEntry[1].Attrib, &DirContext.DirEntry.Fat.Attrib, sizeof(FAT_DIR_ENTRY) - 11);
+            RtlCopyMemory(pFatEntry[1].ShortName, "..         ", 11);
+        }
+
         pFatEntry[1].FirstCluster = ParentFcb->entry.Fat.FirstCluster;
         pFatEntry[1].FirstClusterHigh = ParentFcb->entry.Fat.FirstClusterHigh;
         if (vfatFCBIsRoot(ParentFcb))
@@ -542,7 +650,8 @@ FATXAddEntry(
     IN PVFATFCB* Fcb,
     IN PVFATFCB ParentFcb,
     IN ULONG RequestedOptions,
-    IN UCHAR ReqAttr)
+    IN UCHAR ReqAttr,
+    IN PVFAT_MOVE_CONTEXT MoveContext)
 {
     PVOID Context = NULL;
     LARGE_INTEGER SystemTime, FileOffset;
@@ -578,7 +687,15 @@ FATXAddEntry(
     DirContext.ShortNameU.MaximumLength = 0;
     RtlZeroMemory(&DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY));
     memset(DirContext.DirEntry.FatX.Filename, 0xff, 42);
-    DirContext.DirEntry.FatX.FirstCluster = 0;
+    /* Use cluster, if moving */
+    if (MoveContext != NULL)
+    {
+        DirContext.DirEntry.FatX.FirstCluster = MoveContext->FirstCluster;
+    }
+    else
+    {
+        DirContext.DirEntry.FatX.FirstCluster = 0;
+    }
     DirContext.DirEntry.FatX.FileSize = 0;
 
     /* set file name */
@@ -603,6 +720,13 @@ FATXAddEntry(
     DirContext.DirEntry.FatX.UpdateTime = DirContext.DirEntry.FatX.CreationTime;
     DirContext.DirEntry.FatX.AccessDate = DirContext.DirEntry.FatX.CreationDate;
     DirContext.DirEntry.FatX.AccessTime = DirContext.DirEntry.FatX.CreationTime;
+    /* If it's moving, preserve creation time and file size */
+    if (MoveContext != NULL)
+    {
+        DirContext.DirEntry.FatX.CreationDate = MoveContext->CreationDate;
+        DirContext.DirEntry.FatX.CreationTime = MoveContext->CreationTime;
+        DirContext.DirEntry.FatX.FileSize = MoveContext->FileSize;
+    }
 
     /* add entry into parent directory */
     FileOffset.u.HighPart = 0;
@@ -616,8 +740,19 @@ FATXAddEntry(
     CcSetDirtyPinnedData(Context, NULL);
     CcUnpinData(Context);
 
-    /* FIXME: check status */
-    vfatMakeFCBFromDirEntry(DeviceExt, ParentFcb, &DirContext, Fcb);
+    if (MoveContext != NULL)
+    {
+        /* We're modifying an existing FCB - likely rename/move */
+        /* FIXME: check status */
+        vfatUpdateFCB(DeviceExt, *Fcb, &DirContext.LongNameU, &DirContext.ShortNameU, ParentFcb);
+        (*Fcb)->dirIndex = DirContext.DirIndex;
+        (*Fcb)->startIndex = DirContext.StartIndex;
+    }
+    else
+    {
+        /* FIXME: check status */
+        vfatMakeFCBFromDirEntry(DeviceExt, ParentFcb, &DirContext, Fcb);
+    }
 
     DPRINT("addentry ok\n");
     return STATUS_SUCCESS;
@@ -630,12 +765,13 @@ VfatAddEntry(
     IN PVFATFCB *Fcb,
     IN PVFATFCB ParentFcb,
     IN ULONG RequestedOptions,
-    IN UCHAR ReqAttr)
+    IN UCHAR ReqAttr,
+    IN PVFAT_MOVE_CONTEXT MoveContext)
 {
     if (DeviceExt->Flags & VCB_IS_FATX)
-        return FATXAddEntry(DeviceExt, NameU, Fcb, ParentFcb, RequestedOptions, ReqAttr);
+        return FATXAddEntry(DeviceExt, NameU, Fcb, ParentFcb, RequestedOptions, ReqAttr, MoveContext);
     else
-        return FATAddEntry(DeviceExt, NameU, Fcb, ParentFcb, RequestedOptions, ReqAttr);
+        return FATAddEntry(DeviceExt, NameU, Fcb, ParentFcb, RequestedOptions, ReqAttr, MoveContext);
 }
 
 /*
@@ -644,7 +780,8 @@ VfatAddEntry(
 static NTSTATUS
 FATDelEntry(
     IN PDEVICE_EXTENSION DeviceExt,
-    IN PVFATFCB pFcb)
+    IN PVFATFCB pFcb,
+    OUT PVFAT_MOVE_CONTEXT MoveContext)
 {
     ULONG CurrentCluster = 0, NextCluster, i;
     PVOID Context = NULL;
@@ -687,13 +824,26 @@ FATDelEntry(
         CcUnpinData(Context);
     }
 
-    while (CurrentCluster && CurrentCluster != 0xffffffff)
+    /* In case of moving, don't delete data */
+    if (MoveContext != NULL)
     {
-        GetNextCluster(DeviceExt, CurrentCluster, &NextCluster);
-        /* FIXME: check status */
-        WriteCluster(DeviceExt, CurrentCluster, 0);
-        CurrentCluster = NextCluster;
+        pDirEntry = &pDirEntry[pFcb->dirIndex % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))];
+        MoveContext->FirstCluster = CurrentCluster;
+        MoveContext->FileSize = pDirEntry->FileSize;
+        MoveContext->CreationTime = pDirEntry->CreationTime;
+        MoveContext->CreationDate = pDirEntry->CreationDate;
     }
+    else
+    {
+        while (CurrentCluster && CurrentCluster != 0xffffffff)
+        {
+            GetNextCluster(DeviceExt, CurrentCluster, &NextCluster);
+            /* FIXME: check status */
+            WriteCluster(DeviceExt, CurrentCluster, 0);
+            CurrentCluster = NextCluster;
+        }
+    }
+
     return STATUS_SUCCESS;
 }
 
@@ -703,7 +853,8 @@ FATDelEntry(
 static NTSTATUS
 FATXDelEntry(
     IN PDEVICE_EXTENSION DeviceExt,
-    IN PVFATFCB pFcb)
+    IN PVFATFCB pFcb,
+    OUT PVFAT_MOVE_CONTEXT MoveContext)
 {
     ULONG CurrentCluster = 0, NextCluster;
     PVOID Context = NULL;
@@ -734,25 +885,78 @@ FATXDelEntry(
     CcSetDirtyPinnedData(Context, NULL);
     CcUnpinData(Context);
 
-    while (CurrentCluster && CurrentCluster != 0xffffffff)
+    /* In case of moving, don't delete data */
+    if (MoveContext != NULL)
     {
-        GetNextCluster(DeviceExt, CurrentCluster, &NextCluster);
-        /* FIXME: check status */
-        WriteCluster(DeviceExt, CurrentCluster, 0);
-        CurrentCluster = NextCluster;
+        MoveContext->FirstCluster = CurrentCluster;
+        MoveContext->FileSize = pDirEntry->FileSize;
+        MoveContext->CreationTime = pDirEntry->CreationTime;
+        MoveContext->CreationDate = pDirEntry->CreationDate;
     }
+    else
+    {
+        while (CurrentCluster && CurrentCluster != 0xffffffff)
+        {
+            GetNextCluster(DeviceExt, CurrentCluster, &NextCluster);
+            /* FIXME: check status */
+            WriteCluster(DeviceExt, CurrentCluster, 0);
+            CurrentCluster = NextCluster;
+        }
+    }
+
     return STATUS_SUCCESS;
 }
 
 NTSTATUS
 VfatDelEntry(
     IN PDEVICE_EXTENSION DeviceExt,
-    IN PVFATFCB pFcb)
+    IN PVFATFCB pFcb,
+    OUT PVFAT_MOVE_CONTEXT MoveContext)
 {
     if (DeviceExt->Flags & VCB_IS_FATX)
-        return FATXDelEntry(DeviceExt, pFcb);
+        return FATXDelEntry(DeviceExt, pFcb, MoveContext);
     else
-        return FATDelEntry(DeviceExt, pFcb);
+        return FATDelEntry(DeviceExt, pFcb, MoveContext);
+}
+
+/*
+ * move an existing FAT entry
+ */
+NTSTATUS
+VfatMoveEntry(
+    IN PDEVICE_EXTENSION DeviceExt,
+    IN PVFATFCB pFcb,
+    IN PUNICODE_STRING FileName,
+    IN PVFATFCB ParentFcb)
+{
+    NTSTATUS Status;
+    PVFATFCB OldParent;
+    VFAT_MOVE_CONTEXT MoveContext;
+
+    DPRINT("VfatMoveEntry(%p, %p, %wZ, %p)\n", DeviceExt, pFcb, FileName, ParentFcb);
+
+    /* Delete old entry while keeping data */
+    Status = VfatDelEntry(DeviceExt, pFcb, &MoveContext);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
+    OldParent = pFcb->parentFcb;
+    CcPurgeCacheSection(&OldParent->SectionObjectPointers, NULL, 0, FALSE);
+
+    /* Add our new entry with our cluster */
+    Status = VfatAddEntry(DeviceExt,
+                          FileName,
+                          &pFcb,
+                          ParentFcb,
+                          (vfatFCBIsDirectory(pFcb) ? FILE_DIRECTORY_FILE : 0),
+                          *pFcb->Attributes,
+                          &MoveContext);
+
+    CcPurgeCacheSection(&pFcb->parentFcb->SectionObjectPointers, NULL, 0, FALSE);
+
+    return Status;
 }
 
 /* EOF */
index fad85a2..251821b 100644 (file)
@@ -1,11 +1,12 @@
 /*
-* FILE:             drivers/fs/vfat/fcb.c
+* FILE:             drivers/filesystems/fastfat/fcb.c
 * PURPOSE:          Routines to manipulate FCBs.
 * COPYRIGHT:        See COPYING in the top level directory
 * PROJECT:          ReactOS kernel
 * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
 *                   Rex Jolliff (rex@lvcablemodem.com)
 *                   Herve Poussineau (reactos@poussine.freesurf.fr)
+*                   Pierre Schweitzer (pierre@reactos.org)
 */
 
 /*  -------------------------------------------------------  INCLUDES  */
@@ -156,6 +157,100 @@ vfatNewFCB(
     return  rcFCB;
 }
 
+static
+VOID
+vfatDelFCBFromTable(
+    PDEVICE_EXTENSION pVCB,
+    PVFATFCB pFCB)
+{
+    ULONG Index;
+    ULONG ShortIndex;
+    HASHENTRY* entry;
+
+    Index = pFCB->Hash.Hash % pVCB->HashTableSize;
+    ShortIndex = pFCB->ShortHash.Hash % pVCB->HashTableSize;
+
+    if (pFCB->Hash.Hash != pFCB->ShortHash.Hash)
+    {
+        entry = pVCB->FcbHashTable[ShortIndex];
+        if (entry->self == pFCB)
+        {
+            pVCB->FcbHashTable[ShortIndex] = entry->next;
+        }
+        else
+        {
+            while (entry->next->self != pFCB)
+            {
+                entry = entry->next;
+            }
+            entry->next = pFCB->ShortHash.next;
+        }
+    }
+    entry = pVCB->FcbHashTable[Index];
+    if (entry->self == pFCB)
+    {
+        pVCB->FcbHashTable[Index] = entry->next;
+    }
+    else
+    {
+        while (entry->next->self != pFCB)
+        {
+            entry = entry->next;
+        }
+        entry->next = pFCB->Hash.next;
+    }
+
+    RemoveEntryList(&pFCB->FcbListEntry);
+}
+
+static
+NTSTATUS
+vfatMakeFullName(
+    PVFATFCB directoryFCB,
+    PUNICODE_STRING LongNameU,
+    PUNICODE_STRING ShortNameU,
+    PUNICODE_STRING NameU)
+{
+    PWCHAR PathNameBuffer;
+    USHORT PathNameLength;
+
+    PathNameLength = directoryFCB->PathNameU.Length + max(LongNameU->Length, ShortNameU->Length);
+    if (!vfatFCBIsRoot(directoryFCB))
+    {
+        PathNameLength += sizeof(WCHAR);
+    }
+
+    if (PathNameLength > LONGNAME_MAX_LENGTH * sizeof(WCHAR))
+    {
+        return  STATUS_OBJECT_NAME_INVALID;
+    }
+    PathNameBuffer = ExAllocatePoolWithTag(NonPagedPool, PathNameLength + sizeof(WCHAR), TAG_FCB);
+    if (!PathNameBuffer)
+    {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+    NameU->Buffer = PathNameBuffer;
+    NameU->Length = 0;
+    NameU->MaximumLength = PathNameLength;
+
+    RtlCopyUnicodeString(NameU, &directoryFCB->PathNameU);
+    if (!vfatFCBIsRoot(directoryFCB))
+    {
+        RtlAppendUnicodeToString(NameU, L"\\");
+    }
+    if (LongNameU->Length > 0)
+    {
+        RtlAppendUnicodeStringToString(NameU, LongNameU);
+    }
+    else
+    {
+        RtlAppendUnicodeStringToString(NameU, ShortNameU);
+    }
+    NameU->Buffer[NameU->Length / sizeof(WCHAR)] = 0;
+
+    return STATUS_SUCCESS;
+}
+
 VOID
 vfatDestroyCCB(
     PVFATCCB pCcb)
@@ -182,7 +277,7 @@ BOOLEAN
 vfatFCBIsDirectory(
     PVFATFCB FCB)
 {
-    return *FCB->Attributes & FILE_ATTRIBUTE_DIRECTORY;
+    return ((*FCB->Attributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
 }
 
 BOOLEAN
@@ -197,9 +292,6 @@ vfatReleaseFCB(
     PDEVICE_EXTENSION pVCB,
     PVFATFCB pFCB)
 {
-    HASHENTRY* entry;
-    ULONG Index;
-    ULONG ShortIndex;
     PVFATFCB tmpFcb;
 
     DPRINT("releasing FCB at %p: %wZ, refCount:%d\n",
@@ -207,42 +299,12 @@ vfatReleaseFCB(
 
     while (pFCB)
     {
-        Index = pFCB->Hash.Hash % pVCB->HashTableSize;
-        ShortIndex = pFCB->ShortHash.Hash % pVCB->HashTableSize;
         pFCB->RefCount--;
         if (pFCB->RefCount == 0)
         {
+            ASSERT(pFCB->OpenHandleCount == 0);
             tmpFcb = pFCB->parentFcb;
-            RemoveEntryList (&pFCB->FcbListEntry);
-            if (pFCB->Hash.Hash != pFCB->ShortHash.Hash)
-            {
-                entry = pVCB->FcbHashTable[ShortIndex];
-                if (entry->self == pFCB)
-                {
-                    pVCB->FcbHashTable[ShortIndex] = entry->next;
-                }
-                else
-                {
-                    while (entry->next->self != pFCB)
-                    {
-                        entry = entry->next;
-                    }
-                    entry->next = pFCB->ShortHash.next;
-                }
-            }
-            entry = pVCB->FcbHashTable[Index];
-            if (entry->self == pFCB)
-            {
-                pVCB->FcbHashTable[Index] = entry->next;
-            }
-            else
-            {
-                while (entry->next->self != pFCB)
-                {
-                    entry = entry->next;
-                }
-                entry->next = pFCB->Hash.next;
-            }
+            vfatDelFCBFromTable(pVCB, pFCB);
             vfatDestroyFCB(pFCB);
         }
         else
@@ -253,6 +315,7 @@ vfatReleaseFCB(
     }
 }
 
+static
 VOID
 vfatAddFCBToTable(
     PDEVICE_EXTENSION pVCB,
@@ -279,6 +342,76 @@ vfatAddFCBToTable(
     }
 }
 
+NTSTATUS
+vfatUpdateFCB(
+    PDEVICE_EXTENSION pVCB,
+    PVFATFCB Fcb,
+    PUNICODE_STRING LongName,
+    PUNICODE_STRING ShortName,
+    PVFATFCB ParentFcb)
+{
+    NTSTATUS Status;
+    PVFATFCB OldParent;
+
+    DPRINT("vfatUpdateFCB(%p, %p, %wZ, %wZ, %p)\n", pVCB, Fcb, LongName, ShortName, ParentFcb);
+
+    /* Delete old name */
+    if (Fcb->PathNameBuffer)
+    {
+        ExFreePoolWithTag(Fcb->PathNameBuffer, TAG_FCB);
+    }
+
+    /* Delete from table */
+    vfatDelFCBFromTable(pVCB, Fcb);
+
+    /* Get full path name */
+    Status = vfatMakeFullName(ParentFcb, LongName, ShortName, &Fcb->PathNameU);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
+    /* Split it properly */
+    Fcb->PathNameBuffer = Fcb->PathNameU.Buffer;
+    Fcb->DirNameU.Buffer = Fcb->PathNameU.Buffer;
+    vfatSplitPathName(&Fcb->PathNameU, &Fcb->DirNameU, &Fcb->LongNameU);
+
+    /* Copy short name */
+    RtlCopyUnicodeString(&Fcb->ShortNameU, ShortName);
+
+    /* Recompute hashes */
+    Fcb->Hash.Hash = vfatNameHash(0, &Fcb->PathNameU);
+    if (pVCB->Flags & VCB_IS_FATX)
+    {
+        Fcb->ShortHash.Hash = Fcb->Hash.Hash;
+    }
+    else
+    {
+        Fcb->ShortHash.Hash = vfatNameHash(0, &Fcb->DirNameU);
+        Fcb->ShortHash.Hash = vfatNameHash(Fcb->ShortHash.Hash, &Fcb->ShortNameU);
+    }
+
+    /* Set parent */
+    OldParent = Fcb->parentFcb;
+    Fcb->parentFcb = ParentFcb;
+
+    /* Add to the table */
+    vfatAddFCBToTable(pVCB, Fcb);
+
+    /* If we moved accross directories, dereferenced our old parent
+     * We also derefence in case we're just renaming since AddFCBToTable references it
+     */
+    vfatReleaseFCB(pVCB, OldParent);
+
+    /* In case we were moving accross directories, reset caching on old parent */
+    //if (OldParent != ParentFcb)
+    //{
+    //    CcUninitializeCacheMap(OldParent->FileObject, NULL, NULL);
+    //}
+
+    return STATUS_SUCCESS;
+}
+
 PVFATFCB
 vfatGrabFCBFromTable(
     PDEVICE_EXTENSION pVCB,
@@ -460,47 +593,15 @@ vfatMakeFCBFromDirEntry(
     PVFATFCB *fileFCB)
 {
     PVFATFCB rcFCB;
-    PWCHAR PathNameBuffer;
-    USHORT PathNameLength;
     ULONG Size;
-    ULONG hash;
-
     UNICODE_STRING NameU;
+    NTSTATUS Status;
 
-    PathNameLength = directoryFCB->PathNameU.Length + max(DirContext->LongNameU.Length, DirContext->ShortNameU.Length);
-    if (!vfatFCBIsRoot (directoryFCB))
-    {
-        PathNameLength += sizeof(WCHAR);
-    }
-
-    if (PathNameLength > LONGNAME_MAX_LENGTH * sizeof(WCHAR))
-    {
-        return  STATUS_OBJECT_NAME_INVALID;
-    }
-    PathNameBuffer = ExAllocatePoolWithTag(NonPagedPool, PathNameLength + sizeof(WCHAR), TAG_FCB);
-    if (!PathNameBuffer)
-    {
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-    NameU.Buffer = PathNameBuffer;
-    NameU.Length = 0;
-    NameU.MaximumLength = PathNameLength;
-
-    RtlCopyUnicodeString(&NameU, &directoryFCB->PathNameU);
-    if (!vfatFCBIsRoot(directoryFCB))
-    {
-        RtlAppendUnicodeToString(&NameU, L"\\");
-    }
-    hash = vfatNameHash(0, &NameU);
-    if (DirContext->LongNameU.Length > 0)
-    {
-        RtlAppendUnicodeStringToString(&NameU, &DirContext->LongNameU);
-    }
-    else
+    Status = vfatMakeFullName(directoryFCB, &DirContext->LongNameU, &DirContext->ShortNameU, &NameU);
+    if (!NT_SUCCESS(Status))
     {
-        RtlAppendUnicodeStringToString(&NameU, &DirContext->ShortNameU);
+        return Status;
     }
-    NameU.Buffer[NameU.Length / sizeof(WCHAR)] = 0;
 
     rcFCB = vfatNewFCB(vcb, &NameU);
     RtlCopyMemory(&rcFCB->entry, &DirContext->DirEntry, sizeof (DIR_ENTRY));
@@ -511,7 +612,8 @@ vfatMakeFCBFromDirEntry(
     }
     else
     {
-        rcFCB->ShortHash.Hash = vfatNameHash(hash, &rcFCB->ShortNameU);
+        rcFCB->ShortHash.Hash = vfatNameHash(0, &rcFCB->DirNameU);
+        rcFCB->ShortHash.Hash = vfatNameHash(rcFCB->ShortHash.Hash, &rcFCB->ShortNameU);
     }
 
     if (vfatFCBIsDirectory(rcFCB))
@@ -562,7 +664,7 @@ vfatMakeFCBFromDirEntry(
     vfatAddFCBToTable(vcb, rcFCB);
     *fileFCB = rcFCB;
 
-    ExFreePool(PathNameBuffer);
+    ExFreePool(NameU.Buffer);
     return STATUS_SUCCESS;
 }
 
index d0db178..87a3084 100644 (file)
@@ -1,10 +1,11 @@
 /*
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
- * FILE:             drivers/fs/vfat/finfo.c
+ * FILE:             drivers/filesystems/fastfat/finfo.c
  * PURPOSE:          VFAT Filesystem
  * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
  *                   Herve Poussineau (reactos@poussine.freesurf.fr)
+ *                   Pierre Schweitzer (pierre@reactos.org)
  *
  */
 
@@ -373,6 +374,467 @@ VfatSetDispositionInformation(
     return STATUS_SUCCESS;
 }
 
+static NTSTATUS
+vfatPrepareTargetForRename(
+    IN PDEVICE_EXTENSION DeviceExt,
+    IN PVFATFCB * ParentFCB,
+    IN PUNICODE_STRING NewName,
+    IN BOOLEAN ReplaceIfExists,
+    IN PUNICODE_STRING ParentName,
+    OUT PBOOLEAN Deleted)
+{
+    NTSTATUS Status;
+    PVFATFCB TargetFcb;
+
+    DPRINT("vfatPrepareTargetForRename(%p, %p, %wZ, %d, %wZ, %p)\n", DeviceExt, ParentFCB, NewName, ReplaceIfExists, ParentName);
+
+    *Deleted = FALSE;
+    /* Try to open target */
+    Status = vfatGetFCBForFile(DeviceExt, ParentFCB, &TargetFcb, NewName);
+    /* If it exists */
+    if (NT_SUCCESS(Status))
+    {
+        /* Check whether we are allowed to replace */
+        if (ReplaceIfExists)
+        {
+            /* If that's a directory or a read-only file, we're not allowed */
+            if (vfatFCBIsDirectory(TargetFcb) || ((*TargetFcb->Attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY));
+            {
+                *ParentFCB = NULL;
+                vfatReleaseFCB(DeviceExt, TargetFcb);
+                return STATUS_OBJECT_NAME_COLLISION;
+            }
+
+            /* Attempt to flush (might close the file) */
+            if (!MmFlushImageSection(TargetFcb->FileObject->SectionObjectPointer, MmFlushForDelete))
+            {
+                *ParentFCB = NULL;
+                vfatReleaseFCB(DeviceExt, TargetFcb);
+                return STATUS_ACCESS_DENIED;
+            }
+
+            /* If we are, ensure the file isn't open by anyone! */
+            if (TargetFcb->OpenHandleCount != 0)
+            {
+                *ParentFCB = NULL;
+                vfatReleaseFCB(DeviceExt, TargetFcb);
+                return STATUS_ACCESS_DENIED;
+            }
+
+            /* Effectively delete old file to allow renaming */
+            VfatDelEntry(DeviceExt, TargetFcb, NULL);
+            (*ParentFCB)->RefCount++;
+            vfatReleaseFCB(DeviceExt, TargetFcb);
+            *Deleted = TRUE;
+        }
+        else
+        {
+            *ParentFCB = NULL;
+            vfatReleaseFCB(DeviceExt, TargetFcb);
+            return STATUS_OBJECT_NAME_COLLISION;
+        }
+    }
+    else if (*ParentFCB != NULL)
+    {
+        return STATUS_SUCCESS;
+    }
+
+    /* Failure */
+    return Status;
+}
+
+/*
+ * FUNCTION: Set the file name information
+ */
+static
+NTSTATUS
+VfatSetRenameInformation(
+    PFILE_OBJECT FileObject,
+    PVFATFCB FCB,
+    PDEVICE_EXTENSION DeviceObject,
+    PFILE_RENAME_INFORMATION RenameInfo,
+    PFILE_OBJECT TargetFileObject)
+{
+    NTSTATUS Status;
+    UNICODE_STRING NewName;
+    UNICODE_STRING SourcePath;
+    UNICODE_STRING SourceFile;
+    UNICODE_STRING NewPath;
+    UNICODE_STRING NewFile;
+    PFILE_OBJECT RootFileObject;
+    PVFATFCB RootFCB;
+    UNICODE_STRING RenameInfoString;
+    PVFATFCB ParentFCB;
+    IO_STATUS_BLOCK IoStatusBlock;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    HANDLE TargetHandle;
+    BOOLEAN DeletedTarget;
+
+    DPRINT("VfatSetRenameInfo(%p, %p, %p, %p, %p)\n", FileObject, FCB, DeviceObject, RenameInfo, TargetFileObject);
+
+    /* Disallow renaming root */
+    if (vfatFCBIsRoot(FCB))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* If we are performing relative opening for rename, get FO for getting FCB and path name */
+    if (RenameInfo->RootDirectory != NULL)
+    {
+        /* We cannot tolerate relative opening with a full path */
+        if (RenameInfo->FileName[0] == L'\\')
+        {
+            return STATUS_OBJECT_NAME_INVALID;
+        }
+
+        Status = ObReferenceObjectByHandle(RenameInfo->RootDirectory,
+                                           FILE_READ_DATA,
+                                           *IoFileObjectType,
+                                           ExGetPreviousMode(),
+                                           (PVOID *)&RootFileObject,
+                                           NULL);
+        if (!NT_SUCCESS(Status))
+        {
+            return Status;
+        }
+
+        RootFCB = RootFileObject->FsContext;
+    }
+
+    ParentFCB = NULL;
+
+    if (TargetFileObject == NULL)
+    {
+        /* If we don't have target file object, construct paths thanks to relative FCB, if any, and with
+         * information supplied by the user
+         */
+
+        /* First, setup a string we'll work on */
+        RenameInfoString.Length = RenameInfo->FileNameLength;
+        RenameInfoString.MaximumLength = RenameInfo->FileNameLength;
+        RenameInfoString.Buffer = RenameInfo->FileName;
+
+        /* Check whether we have FQN */
+        if (RenameInfoString.Length > 6 * sizeof(WCHAR))
+        {
+            if (RenameInfoString.Buffer[0] == L'\\' && RenameInfoString.Buffer[1] == L'?' &&
+                RenameInfoString.Buffer[2] == L'?' && RenameInfoString.Buffer[3] == L'\\' &&
+                RenameInfoString.Buffer[5] == L':' && (RenameInfoString.Buffer[4] >= L'A' &&
+                RenameInfoString.Buffer[4] <= L'Z'))
+            {
+                /* If so, open its target directory */
+                InitializeObjectAttributes(&ObjectAttributes,
+                                           &RenameInfoString,
+                                           OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+                                           NULL, NULL);
+
+                Status = IoCreateFile(&TargetHandle,
+                                      FILE_WRITE_DATA | SYNCHRONIZE,
+                                      &ObjectAttributes,
+                                      &IoStatusBlock,
+                                      NULL, 0,
+                                      FILE_SHARE_READ | FILE_SHARE_WRITE,
+                                      FILE_OPEN,
+                                      FILE_OPEN_FOR_BACKUP_INTENT,
+                                      NULL, 0,
+                                      CreateFileTypeNone,
+                                      NULL,
+                                      IO_FORCE_ACCESS_CHECK | IO_OPEN_TARGET_DIRECTORY);
+                if (!NT_SUCCESS(Status))
+                {
+                    goto Cleanup;
+                }
+
+                /* Get its FO to get the FCB */
+                Status = ObReferenceObjectByHandle(TargetHandle,
+                                                   FILE_WRITE_DATA,
+                                                   *IoFileObjectType,
+                                                   KernelMode,
+                                                   (PVOID *)&TargetFileObject,
+                                                   NULL);
+                if (!NT_SUCCESS(Status))
+                {
+                    ZwClose(TargetHandle);
+                    goto Cleanup;
+                }
+
+                /* Are we working on the same volume? */
+                if (IoGetRelatedDeviceObject(TargetFileObject) != IoGetRelatedDeviceObject(FileObject))
+                {
+                    ObDereferenceObject(TargetFileObject);
+                    ZwClose(TargetHandle);
+                    TargetFileObject = NULL;
+                    Status = STATUS_NOT_SAME_DEVICE;
+                    goto Cleanup;
+                }
+            }
+        }
+
+        NewName.Length = 0;
+        NewName.MaximumLength = RenameInfo->FileNameLength;
+        if (RenameInfo->RootDirectory != NULL)
+        {
+            NewName.MaximumLength += sizeof(WCHAR) + RootFCB->PathNameU.Length;
+        }
+        else if (RenameInfo->FileName[0] != L'\\')
+        {
+            /* We don't have full path, and we don't have root directory:
+             * => we move inside the same directory
+             */
+            NewName.MaximumLength += sizeof(WCHAR) + FCB->DirNameU.Length;
+        }
+        else if (TargetFileObject != NULL)
+        {
+            /* We had a FQN:
+             * => we need to use its correct path
+             */
+            NewName.MaximumLength += sizeof(WCHAR) + ((PVFATFCB)TargetFileObject->FsContext)->PathNameU.Length;
+        }
+
+        NewName.Buffer = ExAllocatePoolWithTag(NonPagedPool, NewName.MaximumLength, TAG_VFAT);
+        if (NewName.Buffer == NULL)
+        {
+            if (TargetFileObject != NULL)
+            {
+                ObDereferenceObject(TargetFileObject);
+                ZwClose(TargetHandle);
+                TargetFileObject = NULL;
+            }
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto Cleanup;
+        }
+
+        if (RenameInfo->RootDirectory != NULL)
+        {
+            /* Here, copy first absolute and then append relative */ 
+            RtlCopyUnicodeString(&NewName, &RootFCB->PathNameU);
+            NewName.Buffer[NewName.Length / sizeof(WCHAR)] = L'\\';
+            NewName.Length += sizeof(WCHAR);
+            RtlAppendUnicodeStringToString(&NewName, &RenameInfoString);
+        }
+        else if (RenameInfo->FileName[0] != L'\\')
+        {
+            /* Here, copy first work directory and then append filename */
+            RtlCopyUnicodeString(&NewName, &FCB->DirNameU);
+            NewName.Buffer[NewName.Length / sizeof(WCHAR)] = L'\\';
+            NewName.Length += sizeof(WCHAR);
+            RtlAppendUnicodeStringToString(&NewName, &RenameInfoString);
+        }
+        else if (TargetFileObject != NULL)
+        {
+            /* Here, copy first path name and then append filename */
+            RtlCopyUnicodeString(&NewName, &((PVFATFCB)TargetFileObject->FsContext)->PathNameU);
+            NewName.Buffer[NewName.Length / sizeof(WCHAR)] = L'\\';
+            NewName.Length += sizeof(WCHAR);
+            RtlAppendUnicodeStringToString(&NewName, &RenameInfoString);
+        }
+        else
+        {
+            /* Here we should have full path, so simply copy it */
+            RtlCopyUnicodeString(&NewName, &RenameInfoString);
+        }
+
+        /* Do we have to cleanup some stuff? */
+        if (TargetFileObject != NULL)
+        {
+            ObDereferenceObject(TargetFileObject);
+            ZwClose(TargetHandle);
+            TargetFileObject = NULL;
+        }
+    }
+    else
+    {
+        /* At that point, we shouldn't care about whether we are relative opening
+         * Target FO FCB should already have full path
+         */
+
+        /* Before constructing string, just make a sanity check (just to be sure!) */
+        if (IoGetRelatedDeviceObject(TargetFileObject) != IoGetRelatedDeviceObject(FileObject))
+        {
+            Status = STATUS_NOT_SAME_DEVICE;
+            goto Cleanup;
+        }
+
+        NewName.Length = 0;
+        NewName.MaximumLength = TargetFileObject->FileName.Length + ((PVFATFCB)TargetFileObject->FsContext)->PathNameU.Length + sizeof(WCHAR);
+        NewName.Buffer = ExAllocatePoolWithTag(NonPagedPool, NewName.MaximumLength, TAG_VFAT);
+        if (NewName.Buffer == NULL)
+        {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto Cleanup;
+        }
+
+        RtlCopyUnicodeString(&NewName, &((PVFATFCB)TargetFileObject->FsContext)->PathNameU);
+        NewName.Buffer[NewName.Length / sizeof(WCHAR)] = L'\\';
+        NewName.Length += sizeof(WCHAR);
+        RtlAppendUnicodeStringToString(&NewName, &TargetFileObject->FileName);
+    }
+
+    /* Explode our paths to get path & filename */
+    vfatSplitPathName(&FCB->PathNameU, &SourcePath, &SourceFile);
+    DPRINT("Old dir: %wZ, Old file: %wZ\n", &SourcePath, &SourceFile);
+    vfatSplitPathName(&NewName, &NewPath, &NewFile);
+    DPRINT("New dir: %wZ, New file: %wZ\n", &NewPath, &NewFile);
+
+    /* Are we working in place? */
+    if (FsRtlAreNamesEqual(&SourcePath, &NewPath, TRUE, NULL))
+    {
+        if (FsRtlAreNamesEqual(&SourceFile, &NewFile, FALSE, NULL))
+        {
+            Status = STATUS_SUCCESS;
+            goto Cleanup;
+        }
+
+        if (FsRtlAreNamesEqual(&SourceFile, &NewFile, TRUE, NULL))
+        {
+            FsRtlNotifyFullReportChange(DeviceObject->NotifySync,
+                                        &(DeviceObject->NotifyList),
+                                        (PSTRING)&FCB->PathNameU,
+                                        FCB->PathNameU.Length - FCB->LongNameU.Length,
+                                        NULL,
+                                        NULL,
+                                        ((*FCB->Attributes & FILE_ATTRIBUTE_DIRECTORY) ?
+                                        FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME),
+                                        FILE_ACTION_RENAMED_OLD_NAME,
+                                        NULL);
+            Status = vfatRenameEntry(DeviceObject, FCB, &NewFile, TRUE);
+            if (NT_SUCCESS(Status))
+            {
+                FsRtlNotifyFullReportChange(DeviceObject->NotifySync,
+                                            &(DeviceObject->NotifyList),
+                                            (PSTRING)&FCB->PathNameU,
+                                            FCB->PathNameU.Length - FCB->LongNameU.Length,
+                                            NULL,
+                                            NULL,
+                                            ((*FCB->Attributes & FILE_ATTRIBUTE_DIRECTORY) ?
+                                            FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME),
+                                            FILE_ACTION_RENAMED_NEW_NAME,
+                                            NULL);
+            }
+        }
+        else
+        {
+            /* Try to find target */
+            ParentFCB = FCB->parentFcb;
+            ParentFCB->RefCount++;
+            Status = vfatPrepareTargetForRename(DeviceObject,
+                                                &ParentFCB,
+                                                &NewFile,
+                                                RenameInfo->ReplaceIfExists,
+                                                &NewPath,
+                                                &DeletedTarget);
+            if (!NT_SUCCESS(Status))
+            {
+                goto Cleanup;
+            }
+
+            FsRtlNotifyFullReportChange(DeviceObject->NotifySync,
+                                        &(DeviceObject->NotifyList),
+                                        (PSTRING)&FCB->PathNameU,
+                                        FCB->PathNameU.Length - FCB->LongNameU.Length,
+                                        NULL,
+                                        NULL,
+                                        ((*FCB->Attributes & FILE_ATTRIBUTE_DIRECTORY) ?
+                                        FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME),
+                                        (DeletedTarget ? FILE_ACTION_REMOVED : FILE_ACTION_RENAMED_OLD_NAME),
+                                        NULL);
+            Status = vfatRenameEntry(DeviceObject, FCB, &NewFile, FALSE);
+            if (NT_SUCCESS(Status))
+            {
+                if (DeletedTarget)
+                {
+                    FsRtlNotifyFullReportChange(DeviceObject->NotifySync,
+                                                &(DeviceObject->NotifyList),
+                                                (PSTRING)&FCB->PathNameU,
+                                                FCB->PathNameU.Length - FCB->LongNameU.Length,
+                                                NULL,
+                                                NULL,
+                                                FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE
+                                                | FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_EA,
+                                                FILE_ACTION_MODIFIED,
+                                                NULL);
+                }
+                else
+                {
+                    FsRtlNotifyFullReportChange(DeviceObject->NotifySync,
+                                                &(DeviceObject->NotifyList),
+                                                (PSTRING)&FCB->PathNameU,
+                                                FCB->PathNameU.Length - FCB->LongNameU.Length,
+                                                NULL,
+                                                NULL,
+                                                ((*FCB->Attributes & FILE_ATTRIBUTE_DIRECTORY) ?
+                                                FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME),
+                                                FILE_ACTION_RENAMED_NEW_NAME,
+                                                NULL);
+                }
+            }
+        }
+    }
+    else
+    {
+        /* Try to find target */
+        ParentFCB = NULL;
+        Status = vfatPrepareTargetForRename(DeviceObject,
+                                            &ParentFCB,
+                                            &NewName,
+                                            RenameInfo->ReplaceIfExists,
+                                            &NewPath,
+                                            &DeletedTarget);
+        if (!NT_SUCCESS(Status))
+        {
+            goto Cleanup;
+        }
+
+        FsRtlNotifyFullReportChange(DeviceObject->NotifySync,
+                                    &(DeviceObject->NotifyList),
+                                    (PSTRING)&FCB->PathNameU,
+                                    FCB->PathNameU.Length - FCB->LongNameU.Length,
+                                    NULL,
+                                    NULL,
+                                    ((*FCB->Attributes & FILE_ATTRIBUTE_DIRECTORY) ?
+                                    FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME),
+                                    FILE_ACTION_REMOVED,
+                                    NULL);
+        Status = VfatMoveEntry(DeviceObject, FCB, &NewFile, ParentFCB);
+        if (NT_SUCCESS(Status))
+        {
+            if (DeletedTarget)
+            {
+                FsRtlNotifyFullReportChange(DeviceObject->NotifySync,
+                                            &(DeviceObject->NotifyList),
+                                            (PSTRING)&FCB->PathNameU,
+                                            FCB->PathNameU.Length - FCB->LongNameU.Length,
+                                            NULL,
+                                            NULL,
+                                            FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE
+                                            | FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_EA,
+                                            FILE_ACTION_MODIFIED,
+                                            NULL);
+            }
+            else
+            {
+                FsRtlNotifyFullReportChange(DeviceObject->NotifySync,
+                                            &(DeviceObject->NotifyList),
+                                            (PSTRING)&FCB->PathNameU,
+                                            FCB->PathNameU.Length - FCB->LongNameU.Length,
+                                            NULL,
+                                            NULL,
+                                            ((*FCB->Attributes & FILE_ATTRIBUTE_DIRECTORY) ?
+                                            FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME),
+                                            FILE_ACTION_ADDED,
+                                            NULL);
+            }
+        }
+    }
+
+Cleanup:
+    if (ParentFCB != NULL) vfatReleaseFCB(DeviceObject, ParentFCB);
+    if (NewName.Buffer != NULL) ExFreePoolWithTag(NewName.Buffer, TAG_VFAT);
+    if (RenameInfo->RootDirectory != NULL) ObDereferenceObject(RootFileObject);
+
+    return Status;
+}
+
 /*
  * FUNCTION: Retrieve the file name information
  */
@@ -1005,11 +1467,24 @@ VfatSetInformation(
         DPRINT("Can set file size\n");
     }
 
+    if (FileInformationClass == FileRenameInformation)
+    {
+        if (!ExAcquireResourceExclusiveLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource,
+                                            (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
+        {
+            return VfatQueueRequest(IrpContext);
+        }
+    }
+
     if (!(FCB->Flags & FCB_IS_PAGE_FILE))
     {
         if (!ExAcquireResourceExclusiveLite(&FCB->MainResource,
                                             (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
         {
+            if (FileInformationClass == FileRenameInformation)
+            {
+                ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource);
+            }
             return VfatQueueRequest(IrpContext);
         }
     }
@@ -1044,7 +1519,11 @@ VfatSetInformation(
             break;
 
         case FileRenameInformation:
-            Status = STATUS_NOT_IMPLEMENTED;
+            Status = VfatSetRenameInformation(IrpContext->FileObject,
+                                              FCB,
+                                              IrpContext->DeviceExt,
+                                              SystemBuffer,
+                                              IrpContext->Stack->Parameters.SetFile.FileObject);
             break;
 
         default:
@@ -1056,6 +1535,11 @@ VfatSetInformation(
         ExReleaseResourceLite(&FCB->MainResource);
     }
 
+    if (FileInformationClass == FileRenameInformation)
+    {
+        ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource);
+    }
+
     IrpContext->Irp->IoStatus.Status = Status;
     IrpContext->Irp->IoStatus.Information = 0;
     IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
index 4faab7e..416fa74 100644 (file)
@@ -460,6 +460,13 @@ typedef struct _VFAT_DIRENTRY_CONTEXT
     UNICODE_STRING ShortNameU;
 } VFAT_DIRENTRY_CONTEXT, *PVFAT_DIRENTRY_CONTEXT;
 
+typedef struct _VFAT_MOVE_CONTEXT
+{
+    ULONG FirstCluster;
+    ULONG FileSize;
+    USHORT CreationDate;
+    USHORT CreationTime;
+} VFAT_MOVE_CONTEXT, *PVFAT_MOVE_CONTEXT;
 
 /* blockdev.c */
 
@@ -594,7 +601,8 @@ VfatAddEntry(
     PVFATFCB* Fcb,
     PVFATFCB ParentFcb,
     ULONG RequestedOptions,
-    UCHAR ReqAttr);
+    UCHAR ReqAttr,
+    PVFAT_MOVE_CONTEXT MoveContext);
 
 NTSTATUS
 VfatUpdateEntry(
@@ -603,7 +611,8 @@ VfatUpdateEntry(
 NTSTATUS
 VfatDelEntry(
     PDEVICE_EXTENSION,
-    PVFATFCB);
+    PVFATFCB,
+    PVFAT_MOVE_CONTEXT);
 
 BOOLEAN
 vfatFindDirSpace(
@@ -612,6 +621,20 @@ vfatFindDirSpace(
     ULONG nbSlots,
     PULONG start);
 
+NTSTATUS
+vfatRenameEntry(
+    IN PDEVICE_EXTENSION DeviceExt,
+    IN PVFATFCB pFcb,
+    IN PUNICODE_STRING FileName,
+    IN BOOLEAN CaseChangeOnly);
+
+NTSTATUS
+VfatMoveEntry(
+    IN PDEVICE_EXTENSION DeviceExt,
+    IN PVFATFCB pFcb,
+    IN PUNICODE_STRING FileName,
+    IN PVFATFCB ParentFcb);
+
 /* ea.h */
 
 NTSTATUS
@@ -747,6 +770,14 @@ vfatNewFCB(
     PDEVICE_EXTENSION pVCB,
     PUNICODE_STRING pFileNameU);
 
+NTSTATUS
+vfatUpdateFCB(
+    PDEVICE_EXTENSION pVCB,
+    PVFATFCB Fcb,
+    PUNICODE_STRING LongName,
+    PUNICODE_STRING ShortName,
+    PVFATFCB ParentFcb);
+
 VOID
 vfatDestroyFCB(
     PVFATFCB pFCB);
@@ -765,11 +796,6 @@ vfatReleaseFCB(
     PDEVICE_EXTENSION pVCB,
     PVFATFCB pFCB);
 
-VOID
-vfatAddFCBToTable(
-    PDEVICE_EXTENSION pVCB,
-    PVFATFCB pFCB);
-
 PVFATFCB
 vfatGrabFCBFromTable(
     PDEVICE_EXTENSION pDeviceExt,
index 4be56c6..04fdfe8 100644 (file)
@@ -736,12 +736,12 @@ NpCreateNewNamedPipe(IN PNP_DCB Dcb,
     }
 
     SecurityContext = &AccessState->SubjectSecurityContext;
-    SeLockSubjectContext(&AccessState->SubjectSecurityContext);
+    SeLockSubjectContext(SecurityContext);
 
-    Status = SeAssignSecurity(0,
+    Status = SeAssignSecurity(NULL,
                               AccessState->SecurityDescriptor,
                               &SecurityDescriptor,
-                              0,
+                              FALSE,
                               SecurityContext,
                               IoGetFileObjectGenericMapping(),
                               PagedPool);
@@ -756,7 +756,7 @@ NpCreateNewNamedPipe(IN PNP_DCB Dcb,
     Status = ObLogSecurityDescriptor(SecurityDescriptor,
                                      &CachedSecurityDescriptor,
                                      1);
-    ExFreePool(SecurityDescriptor);
+    ExFreePoolWithTag(SecurityDescriptor, 0);
 
     if (!NT_SUCCESS(Status))
     {
index f2a99b4..60581e1 100644 (file)
@@ -108,15 +108,19 @@ NpInitializeSecurity(IN PNP_CCB Ccb,
         return Status;
     }
 
-    ClientContext = ExAllocatePoolWithTag(PagedPool, sizeof(*ClientContext), NPFS_CLIENT_SEC_CTX_TAG);
+    ClientContext = ExAllocatePoolWithQuotaTag(PagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE,
+                                               sizeof(*ClientContext),
+                                               NPFS_CLIENT_SEC_CTX_TAG);
     Ccb->ClientContext = ClientContext;
     if (!ClientContext) return STATUS_INSUFFICIENT_RESOURCES;
 
     Status = SeCreateClientSecurity(Thread, &Ccb->ClientQos, 0, ClientContext);
-    if (!NT_SUCCESS(Status)) return Status;
+    if (!NT_SUCCESS(Status))
+    {
+        ExFreePool(Ccb->ClientContext);
+        Ccb->ClientContext = NULL;
+    }
 
-    ExFreePool(Ccb->ClientContext);
-    Ccb->ClientContext = NULL;
     return Status;
 }
 
index 546388d..1678ef2 100644 (file)
@@ -85,7 +85,8 @@ NpCommonSetSecurityInfo(IN PDEVICE_OBJECT DeviceObject,
     if (!NT_SUCCESS(Status)) return Status;
 
     Status = ObLogSecurityDescriptor(TempSecurityDescriptor, &NewSecurityDescriptor, 1);
-    ExFreePool(TempSecurityDescriptor);
+    ASSERT(TempSecurityDescriptor != OldSecurityDescriptor);
+    ExFreePoolWithTag(TempSecurityDescriptor, 0);
 
     if (!NT_SUCCESS(Status)) return Status;
 
index 28c1877..a078686 100644 (file)
@@ -175,17 +175,16 @@ NtfsGetDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
         ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION) + Length, sizeof(ULONG));
     RtlCopyMemory(Info->FileName, FileName->Name, Length);
 
-    /* Convert file times */
-    NtfsDateTimeToFileTime(FileName->CreationTime, &Info->CreationTime);
-    NtfsDateTimeToFileTime(FileName->LastAccessTime, &Info->LastAccessTime);
-    NtfsDateTimeToFileTime(FileName->LastWriteTime, &Info->LastWriteTime);
-    NtfsDateTimeToFileTime(FileName->ChangeTime, &Info->ChangeTime);
+    Info->CreationTime.QuadPart = FileName->CreationTime;
+    Info->LastAccessTime.QuadPart = FileName->LastAccessTime;
+    Info->LastWriteTime.QuadPart = FileName->LastWriteTime;
+    Info->ChangeTime.QuadPart = FileName->ChangeTime;
 
     /* Convert file flags */
     NtfsFileFlagsToAttributes(FileName->FileAttributes, &Info->FileAttributes);
 
-    Info->EndOfFile.QuadPart = FileName->DataSize;
-    Info->AllocationSize.QuadPart = FileName->AllocatedSize;
+    Info->EndOfFile.QuadPart = FileName->AllocatedSize;
+    Info->AllocationSize.QuadPart = ROUND_UP(FileName->AllocatedSize, DeviceExt->NtfsInfo.BytesPerCluster);
 
 //  Info->FileIndex=;
 
@@ -217,17 +216,16 @@ NtfsGetFullDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
         ROUND_UP(sizeof(FILE_FULL_DIRECTORY_INFORMATION) + Length, sizeof(ULONG));
     RtlCopyMemory(Info->FileName, FileName->Name, Length);
 
-    /* Convert file times */
-    NtfsDateTimeToFileTime(FileName->CreationTime, &Info->CreationTime);
-    NtfsDateTimeToFileTime(FileName->LastAccessTime, &Info->LastAccessTime);
-    NtfsDateTimeToFileTime(FileName->LastWriteTime, &Info->LastWriteTime);
-    NtfsDateTimeToFileTime(FileName->ChangeTime, &Info->ChangeTime);
+    Info->CreationTime.QuadPart = FileName->CreationTime;
+    Info->LastAccessTime.QuadPart = FileName->LastAccessTime;
+    Info->LastWriteTime.QuadPart = FileName->LastWriteTime;
+    Info->ChangeTime.QuadPart = FileName->ChangeTime;
 
     /* Convert file flags */
     NtfsFileFlagsToAttributes(FileName->FileAttributes, &Info->FileAttributes);
 
-    Info->EndOfFile.QuadPart = FileName->DataSize;
-    Info->AllocationSize.QuadPart = FileName->AllocatedSize;
+    Info->EndOfFile.QuadPart = FileName->AllocatedSize;
+    Info->AllocationSize.QuadPart = ROUND_UP(FileName->AllocatedSize, DeviceExt->NtfsInfo.BytesPerCluster);
 
 //  Info->FileIndex=;
     Info->EaSize = 0;
@@ -260,17 +258,16 @@ NtfsGetBothDirectoryInformation(PDEVICE_EXTENSION DeviceExt,
         ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION) + Length, sizeof(ULONG));
     RtlCopyMemory(Info->FileName, FileName->Name, Length);
 
-    /* Convert file times */
-    NtfsDateTimeToFileTime(FileName->CreationTime, &Info->CreationTime);
-    NtfsDateTimeToFileTime(FileName->LastAccessTime, &Info->LastAccessTime);
-    NtfsDateTimeToFileTime(FileName->LastWriteTime, &Info->LastWriteTime);
-    NtfsDateTimeToFileTime(FileName->ChangeTime, &Info->ChangeTime);
+    Info->CreationTime.QuadPart = FileName->CreationTime;
+    Info->LastAccessTime.QuadPart = FileName->LastAccessTime;
+    Info->LastWriteTime.QuadPart = FileName->LastWriteTime;
+    Info->ChangeTime.QuadPart = FileName->ChangeTime;
 
     /* Convert file flags */
     NtfsFileFlagsToAttributes(FileName->FileAttributes, &Info->FileAttributes);
 
-    Info->EndOfFile.QuadPart = FileName->DataSize;
-    Info->AllocationSize.QuadPart = FileName->AllocatedSize;
+    Info->EndOfFile.QuadPart = FileName->AllocatedSize;
+    Info->AllocationSize.QuadPart = ROUND_UP(FileName->AllocatedSize, DeviceExt->NtfsInfo.BytesPerCluster);
 
 //  Info->FileIndex=;
     Info->EaSize = 0;
index d1a4ffc..91593e5 100644 (file)
@@ -97,18 +97,6 @@ NtfsAllocateIrpContext(PDEVICE_OBJECT DeviceObject,
     return IrpContext;
 }
 
-/* See:
- -> http://msdn.microsoft.com/en-us/library/ms724228
- -> http://bos.asmhackers.net/docs/filesystems/ntfs/standard.html#layout
- */
-VOID
-NtfsDateTimeToFileTime(ULONGLONG NtfsTime,
-                       PLARGE_INTEGER SystemTime)
-{
-
-    SystemTime->QuadPart = NtfsTime + 116444736000000000;
-}
-
 VOID
 NtfsFileFlagsToAttributes(ULONG NtfsAttributes,
                           PULONG FileAttributes)
index eb75a8c..663cba2 100644 (file)
@@ -692,10 +692,6 @@ CdfsSwapString(PWCHAR Out,
               ULONG Count);
 #endif
 
-VOID
-NtfsDateTimeToFileTime(ULONGLONG NtfsTime,
-                       PLARGE_INTEGER SystemTime);
-
 VOID
 NtfsFileFlagsToAttributes(ULONG NtfsAttributes,
                           PULONG FileAttributes);
index 21a64fe..15767d0 100644 (file)
@@ -56,7 +56,6 @@ NTSTATUS WarmSocketForBind( PAFD_FCB FCB, ULONG ShareType ) {
                                         FCB->Recv.Window,
                                         FCB->Recv.Size,
                                         FCB->AddressFrom,
-                                        &FCB->ReceiveIrp.Iosb,
                                         PacketSocketRecvComplete,
                                         FCB);
 
index 7a08fdf..0144741 100644 (file)
@@ -286,7 +286,6 @@ MakeSocketIntoConnection(PAFD_FCB FCB) {
                          TDI_RECEIVE_NORMAL,
                          FCB->Recv.Window,
                          FCB->Recv.Size,
-                         &FCB->ReceiveIrp.Iosb,
                          ReceiveComplete,
                          FCB );
 
@@ -518,7 +517,6 @@ AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
                                 FCB->Connection.Object,
                                 FCB->ConnectCallInfo,
                                 FCB->ConnectReturnInfo,
-                                &FCB->ConnectIrp.Iosb,
                                 StreamSocketConnectComplete,
                                 FCB );
         }
index 94893fc..120ad11 100644 (file)
@@ -191,7 +191,6 @@ static NTSTATUS NTAPI ListenComplete( PDEVICE_OBJECT DeviceObject,
                             FCB->Connection.Object,
                             &FCB->ListenIrp.ConnectionCallInfo,
                             &FCB->ListenIrp.ConnectionReturnInfo,
-                            &FCB->ListenIrp.Iosb,
                             ListenComplete,
                             FCB );
 
@@ -268,7 +267,6 @@ NTSTATUS AfdListenSocket( PDEVICE_OBJECT DeviceObject, PIRP Irp,
                         FCB->Connection.Object,
                         &FCB->ListenIrp.ConnectionCallInfo,
                         &FCB->ListenIrp.ConnectionReturnInfo,
-                        &FCB->ListenIrp.Iosb,
                         ListenComplete,
                         FCB );
 
index 97da39b..c4feb08 100644 (file)
@@ -662,7 +662,6 @@ DoDisconnect(PAFD_FCB FCB)
                            FCB->Connection.Object,
                            &FCB->DisconnectTimeout,
                            FCB->DisconnectFlags,
-                           &FCB->DisconnectIrp.Iosb,
                            DisconnectComplete,
                            FCB,
                            FCB->ConnectCallInfo,
index 6e02a67..935379e 100644 (file)
@@ -46,7 +46,6 @@ static VOID RefillSocketBuffer( PAFD_FCB FCB )
                 TDI_RECEIVE_NORMAL,
                 FCB->Recv.Window + FCB->Recv.Content,
                 FCB->Recv.Size - FCB->Recv.Content,
-                &FCB->ReceiveIrp.Iosb,
                 ReceiveComplete,
                 FCB );
 }
@@ -691,7 +690,6 @@ PacketSocketRecvComplete(
               FCB->Recv.Window,
               FCB->Recv.Size,
               FCB->AddressFrom,
-              &FCB->ReceiveIrp.Iosb,
               PacketSocketRecvComplete,
               FCB );
     }
index a36a09d..333462e 100644 (file)
@@ -329,7 +329,6 @@ NTSTATUS TdiConnect(
     PFILE_OBJECT ConnectionObject,
     PTDI_CONNECTION_INFORMATION ConnectionCallInfo,
     PTDI_CONNECTION_INFORMATION ConnectionReturnInfo,
-    PIO_STATUS_BLOCK Iosb,
     PIO_COMPLETION_ROUTINE CompletionRoutine,
     PVOID CompletionContext)
 /*
@@ -362,7 +361,7 @@ NTSTATUS TdiConnect(
                                             DeviceObject,            /* Device object */
                                             ConnectionObject,        /* File object */
                                             NULL,                    /* Event */
-                                            Iosb);                   /* Status */
+                                            NULL);                   /* Status */
     if (!*Irp) {
         return STATUS_INSUFFICIENT_RESOURCES;
     }
@@ -376,7 +375,7 @@ NTSTATUS TdiConnect(
                     ConnectionCallInfo,     /* Request connection information */
                     ConnectionReturnInfo);  /* Return connection information */
 
-    TdiCall(*Irp, DeviceObject, NULL, Iosb);
+    TdiCall(*Irp, DeviceObject, NULL, NULL);
 
     return STATUS_PENDING;
 }
@@ -485,7 +484,6 @@ NTSTATUS TdiListen(
     PFILE_OBJECT ConnectionObject,
     PTDI_CONNECTION_INFORMATION *RequestConnectionInfo,
     PTDI_CONNECTION_INFORMATION *ReturnConnectionInfo,
-    PIO_STATUS_BLOCK Iosb,
     PIO_COMPLETION_ROUTINE  CompletionRoutine,
     PVOID CompletionContext)
 /*
@@ -519,7 +517,7 @@ NTSTATUS TdiListen(
                                             DeviceObject,            /* Device object */
                                             ConnectionObject,        /* File object */
                                             NULL,                    /* Event */
-                                            Iosb);                   /* Status */
+                                            NULL);                   /* Status */
     if (*Irp == NULL)
         return STATUS_INSUFFICIENT_RESOURCES;
 
@@ -532,7 +530,7 @@ NTSTATUS TdiListen(
                    *RequestConnectionInfo, /* Request connection information */
                    *ReturnConnectionInfo);  /* Return connection information */
 
-    TdiCall(*Irp, DeviceObject, NULL /* Don't wait for completion */, Iosb);
+    TdiCall(*Irp, DeviceObject, NULL /* Don't wait for completion */, NULL);
 
     return STATUS_PENDING;
 }
@@ -892,7 +890,6 @@ NTSTATUS TdiSend(
     USHORT Flags,
     PCHAR Buffer,
     UINT BufferLength,
-    PIO_STATUS_BLOCK Iosb,
     PIO_COMPLETION_ROUTINE CompletionRoutine,
     PVOID CompletionContext)
 {
@@ -916,7 +913,7 @@ NTSTATUS TdiSend(
                                             DeviceObject,            /* Device object */
                                             TransportObject,         /* File object */
                                             NULL,                    /* Event */
-                                            Iosb);                   /* Status */
+                                            NULL);                   /* Status */
 
     if (!*Irp) {
         AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
@@ -958,7 +955,7 @@ NTSTATUS TdiSend(
                  Flags,                  /* Flags */
                  BufferLength);          /* Length of data */
 
-    TdiCall(*Irp, DeviceObject, NULL, Iosb);
+    TdiCall(*Irp, DeviceObject, NULL, NULL);
     /* Does not block...  The MDL is deleted in the receive completion
        routine. */
 
@@ -971,7 +968,6 @@ NTSTATUS TdiReceive(
     USHORT Flags,
     PCHAR Buffer,
     UINT BufferLength,
-    PIO_STATUS_BLOCK Iosb,
     PIO_COMPLETION_ROUTINE CompletionRoutine,
     PVOID CompletionContext)
 {
@@ -995,7 +991,7 @@ NTSTATUS TdiReceive(
                                             DeviceObject,            /* Device object */
                                             TransportObject,         /* File object */
                                             NULL,                    /* Event */
-                                            Iosb);                   /* Status */
+                                            NULL);                   /* Status */
 
     if (!*Irp) {
         AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
@@ -1040,7 +1036,7 @@ NTSTATUS TdiReceive(
                     BufferLength);          /* Length of data */
 
 
-    TdiCall(*Irp, DeviceObject, NULL, Iosb);
+    TdiCall(*Irp, DeviceObject, NULL, NULL);
     /* Does not block...  The MDL is deleted in the receive completion
        routine. */
 
@@ -1055,7 +1051,6 @@ NTSTATUS TdiReceiveDatagram(
     PCHAR Buffer,
     UINT BufferLength,
     PTDI_CONNECTION_INFORMATION Addr,
-    PIO_STATUS_BLOCK Iosb,
     PIO_COMPLETION_ROUTINE CompletionRoutine,
     PVOID CompletionContext)
 /*
@@ -1090,7 +1085,7 @@ NTSTATUS TdiReceiveDatagram(
                                             DeviceObject,            /* Device object */
                                             TransportObject,         /* File object */
                                             NULL,                    /* Event */
-                                            Iosb);                   /* Status */
+                                            NULL);                   /* Status */
 
     if (!*Irp) {
         AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
@@ -1134,7 +1129,7 @@ NTSTATUS TdiReceiveDatagram(
                             Addr,
                             Flags);                 /* Length of data */
 
-    TdiCall(*Irp, DeviceObject, NULL, Iosb);
+    TdiCall(*Irp, DeviceObject, NULL, NULL);
     /* Does not block...  The MDL is deleted in the receive completion
        routine. */
 
@@ -1148,7 +1143,6 @@ NTSTATUS TdiSendDatagram(
     PCHAR Buffer,
     UINT BufferLength,
     PTDI_CONNECTION_INFORMATION Addr,
-    PIO_STATUS_BLOCK Iosb,
     PIO_COMPLETION_ROUTINE CompletionRoutine,
     PVOID CompletionContext)
 /*
@@ -1185,7 +1179,7 @@ NTSTATUS TdiSendDatagram(
                                             DeviceObject,            /* Device object */
                                             TransportObject,         /* File object */
                                             NULL,                    /* Event */
-                                            Iosb);                   /* Status */
+                                            NULL);                   /* Status */
 
     if (!*Irp) {
         AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
@@ -1228,7 +1222,7 @@ NTSTATUS TdiSendDatagram(
                          BufferLength,           /* Bytes to send */
                          Addr);                  /* Address */
 
-    TdiCall(*Irp, DeviceObject, NULL, Iosb);
+    TdiCall(*Irp, DeviceObject, NULL, NULL);
     /* Does not block...  The MDL is deleted in the send completion
        routine. */
 
@@ -1240,7 +1234,6 @@ NTSTATUS TdiDisconnect(
     PFILE_OBJECT TransportObject,
     PLARGE_INTEGER Time,
     USHORT Flags,
-    PIO_STATUS_BLOCK Iosb,
     PIO_COMPLETION_ROUTINE CompletionRoutine,
     PVOID CompletionContext,
     PTDI_CONNECTION_INFORMATION RequestConnectionInfo,
@@ -1264,7 +1257,7 @@ NTSTATUS TdiDisconnect(
                                             DeviceObject,            /* Device object */
                                             TransportObject,         /* File object */
                                             NULL,                    /* Event */
-                                            Iosb);                   /* Status */
+                                            NULL);                   /* Status */
 
     if (!*Irp) {
         AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
@@ -1281,7 +1274,7 @@ NTSTATUS TdiDisconnect(
                        RequestConnectionInfo,  /* Indication of who to disconnect */
                        ReturnConnectionInfo);  /* Indication of who disconnected */
 
-    TdiCall(*Irp, DeviceObject, NULL, Iosb);
+    TdiCall(*Irp, DeviceObject, NULL, NULL);
 
     return STATUS_PENDING;
 }
index 3f07109..b91593c 100644 (file)
@@ -243,7 +243,6 @@ static NTSTATUS NTAPI SendComplete
                           0,
                           FCB->Send.Window,
                           FCB->Send.BytesUsed,
-                          &FCB->SendIrp.Iosb,
                           SendComplete,
                           FCB );
     }
@@ -385,7 +384,6 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
                                 SendReq->BufferArray[0].buf,
                                 SendReq->BufferArray[0].len,
                                 TargetAddress,
-                                &FCB->SendIrp.Iosb,
                                 PacketSocketSendComplete,
                                 FCB);
             }
@@ -549,7 +547,6 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
                 0,
                 FCB->Send.Window,
                 FCB->Send.BytesUsed,
-                &FCB->SendIrp.Iosb,
                 SendComplete,
                 FCB);
     }
@@ -645,7 +642,6 @@ AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
                             SendReq->BufferArray[0].buf,
                             SendReq->BufferArray[0].len,
                             TargetAddress,
-                            &FCB->SendIrp.Iosb,
                             PacketSocketSendComplete,
                             FCB);
         }
index f27ce8f..36aed14 100644 (file)
@@ -152,7 +152,6 @@ typedef struct _AFD_TDI_OBJECT_QELT {
 
 typedef struct _AFD_IN_FLIGHT_REQUEST {
     PIRP InFlightRequest;
-    IO_STATUS_BLOCK Iosb;
     PTDI_CONNECTION_INFORMATION ConnectionCallInfo;
     PTDI_CONNECTION_INFORMATION ConnectionReturnInfo;
 } AFD_IN_FLIGHT_REQUEST, *PAFD_IN_FLIGHT_REQUEST;
@@ -369,7 +368,6 @@ NTSTATUS TdiListen
   PFILE_OBJECT ConnectionObject,
   PTDI_CONNECTION_INFORMATION *RequestConnectionInfo,
   PTDI_CONNECTION_INFORMATION *ReturnConnectionInfo,
-  PIO_STATUS_BLOCK Iosb,
   PIO_COMPLETION_ROUTINE  CompletionRoutine,
   PVOID CompletionContext);
 
@@ -379,7 +377,6 @@ NTSTATUS TdiReceive
   USHORT Flags,
   PCHAR Buffer,
   UINT BufferLength,
-  PIO_STATUS_BLOCK Iosb,
   PIO_COMPLETION_ROUTINE  CompletionRoutine,
   PVOID CompletionContext);
 
@@ -389,7 +386,6 @@ NTSTATUS TdiSend
   USHORT Flags,
   PCHAR Buffer,
   UINT BufferLength,
-  PIO_STATUS_BLOCK Iosb,
   PIO_COMPLETION_ROUTINE  CompletionRoutine,
   PVOID CompletionContext);
 
@@ -400,7 +396,6 @@ NTSTATUS TdiReceiveDatagram(
     PCHAR Buffer,
     UINT BufferLength,
     PTDI_CONNECTION_INFORMATION From,
-    PIO_STATUS_BLOCK Iosb,
     PIO_COMPLETION_ROUTINE CompletionRoutine,
     PVOID CompletionContext);
 
@@ -410,7 +405,6 @@ NTSTATUS TdiSendDatagram(
     PCHAR Buffer,
     UINT BufferLength,
     PTDI_CONNECTION_INFORMATION To,
-    PIO_STATUS_BLOCK Iosb,
     PIO_COMPLETION_ROUTINE CompletionRoutine,
     PVOID CompletionContext);
 
index 277cf73..e8ee566 100644 (file)
@@ -4,7 +4,6 @@ NTSTATUS TdiConnect( PIRP *PendingIrp,
                     PFILE_OBJECT ConnectionObject,
                     PTDI_CONNECTION_INFORMATION ConnectionCallInfo,
                     PTDI_CONNECTION_INFORMATION ConnectionReturnInfo,
-                    PIO_STATUS_BLOCK Iosb,
                     PIO_COMPLETION_ROUTINE CompletionRoutine,
                     PVOID CompletionContext );
 
@@ -20,7 +19,6 @@ NTSTATUS TdiDisconnect
   PFILE_OBJECT TransportObject,
   PLARGE_INTEGER Time,
   USHORT Flags,
-  PIO_STATUS_BLOCK Iosb,
   PIO_COMPLETION_ROUTINE CompletionRoutine,
   PVOID CompletionContext,
   PTDI_CONNECTION_INFORMATION RequestConnectionInfo,
index d58319d..47d4bde 100644 (file)
@@ -1692,7 +1692,7 @@ IssueIdentify(
                 deviceExtension->FullIdentifyData.NVCache_Version
                 ));
 
-        KdPrint2((PRINT_PREFIX "R-rate %#x\n",
+        KdPrint2((PRINT_PREFIX "R-rate %d\n",
                 deviceExtension->FullIdentifyData.NominalMediaRotationRate
                 ));
 
@@ -5071,9 +5071,9 @@ continue_err:
                     if(AtaReq->retry < MAX_RETRIES) {
 //fallback_pio:
                         if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
-                            AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
+                            //AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
+                            // Downrate will happen in AtapiDmaReinit(), try UDMA-2 for HDD only
                             AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
-//                        LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
                         }
                         AtaReq->ReqState = REQ_STATE_QUEUED;
                         goto reenqueue_req;
@@ -5093,6 +5093,7 @@ continue_err:
                ((error >> 4) == SCSI_SENSE_HARDWARE_ERROR)) {
                 if(AtaReq->retry < MAX_RETRIES) {
 //fallback_pio:
+                    // Downrate will happen in AtapiDmaReinit(), use PIO immediately for ATAPI
                     AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
                     AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
 //                        LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
@@ -5449,6 +5450,7 @@ IntrPrepareResetController:
             chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
             goto CompleteRequest;
         }
+continue_read_drq:
         // Ensure that this is a read command.
         if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
 
@@ -5489,7 +5491,6 @@ IntrPrepareResetController:
                         }
                     }
                 }
-
             } else {
                 KdPrint2((PRINT_PREFIX 
                           "IdeIntr: Read %#x Dwords\n", wordCount/2));
@@ -5581,6 +5582,12 @@ IntrPrepareResetController:
                     status = SRB_STATUS_SUCCESS;
                     goto CompleteRequest;
                 }
+            } else {
+                if(!atapiDev && !DataOverrun && (srb->SrbFlags & SRB_FLAGS_DATA_IN) &&
+                    (statusByte == (IDE_STATUS_IDLE | IDE_STATUS_DRQ))) {
+                    KdPrint2((PRINT_PREFIX "  HDD read data ready \n"));
+                    goto continue_read_drq;
+                }
             }
         }
 
@@ -6689,6 +6696,7 @@ IdeReadWrite(
     // Adjust buffer address and words left count.
     AtaReq->WordsLeft -= wordCount;
     AtaReq->DataBuffer += wordCount;
+    AtaReq->WordsTransfered += wordCount;
 
     // Wait for interrupt.
     return SRB_STATUS_PENDING;
index 800d02d..00a0560 100644 (file)
@@ -587,10 +587,8 @@ AtapiDmaStart(
     case ATA_PROMISE_ID:
         if(ChipType == PRNEW) {
             ULONG Channel = deviceExtension->Channel + lChannel;
+
             if(chan->ChannelCtrlFlags & CTRFLAGS_LBA48) {
-                AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11,
-                      AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11) |
-                          (Channel ? 0x08 : 0x02));
                 AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),(Channel ? 0x24 : 0x20),
                       ((Srb->SrbFlags & SRB_FLAGS_DATA_IN) ? 0x05000000 : 0x06000000) | (Srb->DataTransferLength >> 1)
                       );
@@ -659,10 +657,12 @@ AtapiDmaDone(
     case ATA_PROMISE_ID:
         if(ChipType == PRNEW) {
             ULONG Channel = deviceExtension->Channel + lChannel;
+/*
+            AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11,
+                  AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11) &
+                      ~(Channel ? 0x08 : 0x02));
+*/
             if(chan->ChannelCtrlFlags & CTRFLAGS_LBA48) {
-                AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11,
-                      AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11) &
-                          ~(Channel ? 0x08 : 0x02));
                 AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),(Channel ? 0x24 : 0x20),
                       0
                       );
@@ -1555,10 +1555,13 @@ set_new_acard:
 
         return;
         break; }
-    case ATA_PROMISE_ID:
+    case ATA_PROMISE_ID: {
         /***********/
         /* Promise */
         /***********/
+
+       UCHAR sel66 = Channel ? 0x08: 0x02;
+
         if(ChipType < PRTX) {
             if (isAtapi) {
                 udmamode =
@@ -1566,12 +1569,29 @@ set_new_acard:
             }
         }
         for(i=udmamode; i>=0; i--) {
+
+            if(ChipType == PRNEW) {
+              if(i>2) {
+                AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11,
+                      AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11) |
+                          sel66);
+              } else {
+                AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11,
+                      AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11) &
+                          ~sel66);
+              }
+            }
+
             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
                 promise_timing(deviceExtension, dev, (UCHAR)(ATA_UDMA + i));       // ???
                 return;
             }
         }
-
+        if(ChipType == PRNEW) {
+          AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11,
+              AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11) &
+                  ~sel66);
+        }
         for(i=wdmamode; i>=0; i--) {
             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
                 promise_timing(deviceExtension, dev, (UCHAR)(ATA_WDMA0+i));
@@ -1587,7 +1607,7 @@ set_new_acard:
         AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
         promise_timing(deviceExtension, dev, ATA_PIO0 + apiomode);
         return;
-        break;
+        break; }
     case ATA_ATI_ID:
 
         KdPrint2((PRINT_PREFIX "ATI\n"));
index 7d099e7..6e449ed 100644 (file)
@@ -968,6 +968,12 @@ UniataAhciDetect(
     KdPrint2((PRINT_PREFIX "\n"));
 
     /* get the number of HW channels */
+    
+    /* CAP.NOP sometimes indicate the index of the last enabled
+     * port, at other times, that of the last possible port, so
+     * determining the maximum port number requires looking at
+     * both CAP.NOP and PI.
+     */
     PI = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_PI);
     deviceExtension->AHCI_PI = PI;
     KdPrint2((PRINT_PREFIX "  AHCI PI %#x\n", PI));
index e3d79e5..3c30c7d 100644 (file)
@@ -1,10 +1,10 @@
-#define UNIATA_VER_STR         "45a8"
-#define UNIATA_VER_DOT         0.45.1.8
+#define UNIATA_VER_STR         "45b1"
+#define UNIATA_VER_DOT         0.45.2.1
 #define UNIATA_VER_MJ          0
 #define UNIATA_VER_MN          45
-#define UNIATA_VER_SUB_MJ      1
-#define UNIATA_VER_SUB_MN      8
-#define UNIATA_VER_DOT_COMMA   0,45,1,8
-#define UNIATA_VER_DOT_STR     "0.45.1.8"
+#define UNIATA_VER_SUB_MJ      2
+#define UNIATA_VER_SUB_MN      1
+#define UNIATA_VER_DOT_COMMA   0,45,2,1
+#define UNIATA_VER_DOT_STR     "0.45.2.1"
 #define UNIATA_VER_YEAR        2014
 #define UNIATA_VER_YEAR_STR    "2014"
index d9ae74f..3afd246 100644 (file)
@@ -1374,6 +1374,22 @@ Language=English
 DRIVER_LEFT_LOCKED_PAGES_IN_PROCESS
 .
 
+MessageId=0xCC
+Severity=Success
+Facility=System
+SymbolicName=PAGE_FAULT_IN_FREED_SPECIAL_POOL
+Language=English
+PAGE_FAULT_IN_FREED_SPECIAL_POOL
+.
+
+MessageId=0xCD
+Severity=Success
+Facility=System
+SymbolicName=PAGE_FAULT_BEYOND_END_OF_ALLOCATION
+Language=English
+PAGE_FAULT_BEYOND_END_OF_ALLOCATION
+.
+
 MessageId=0xCE
 Severity=Success
 Facility=System
@@ -1406,6 +1422,22 @@ Language=English
 The driver mistakenly marked a part of its image pageable instead of non-pageable.
 .
 
+MessageId=0xD5
+Severity=Success
+Facility=System
+SymbolicName=DRIVER_PAGE_FAULT_IN_FREED_SPECIAL_POOL
+Language=English
+DRIVER_PAGE_FAULT_IN_FREED_SPECIAL_POOL
+.
+
+MessageId=0xD6
+Severity=Success
+Facility=System
+SymbolicName=DRIVER_PAGE_FAULT_BEYOND_END_OF_ALLOCATION
+Language=English
+DRIVER_PAGE_FAULT_BEYOND_END_OF_ALLOCATION
+.
+
 MessageId=0xD7
 Severity=Success
 Facility=System
index 5032c76..abeac0b 100644 (file)
@@ -21,8 +21,6 @@
 
 #include "strmbase_private.h"
 
-static const IPinVtbl InputPin_Vtbl;
-static const IPinVtbl OutputPin_Vtbl;
 static const IMemInputPinVtbl MemInputPin_Vtbl;
 
 typedef HRESULT (*SendPinFunc)( IPin *to, LPVOID arg );
@@ -545,28 +543,6 @@ HRESULT WINAPI BaseOutputPinImpl_EndFlush(IPin * iface)
     return E_UNEXPECTED;
 }
 
-static const IPinVtbl OutputPin_Vtbl =
-{
-    BaseOutputPinImpl_QueryInterface,
-    BasePinImpl_AddRef,
-    BaseOutputPinImpl_Release,
-    BaseOutputPinImpl_Connect,
-    BaseOutputPinImpl_ReceiveConnection,
-    BaseOutputPinImpl_Disconnect,
-    BasePinImpl_ConnectedTo,
-    BasePinImpl_ConnectionMediaType,
-    BasePinImpl_QueryPinInfo,
-    BasePinImpl_QueryDirection,
-    BasePinImpl_QueryId,
-    BasePinImpl_QueryAccept,
-    BasePinImpl_EnumMediaTypes,
-    BasePinImpl_QueryInternalConnections,
-    BaseOutputPinImpl_EndOfStream,
-    BaseOutputPinImpl_BeginFlush,
-    BaseOutputPinImpl_EndFlush,
-    BasePinImpl_NewSegment
-};
-
 HRESULT WINAPI BaseOutputPinImpl_GetDeliveryBuffer(BaseOutputPin *This, IMediaSample ** ppSample, REFERENCE_TIME * tStart, REFERENCE_TIME * tStop, DWORD dwFlags)
 {
     HRESULT hr;
@@ -851,11 +827,6 @@ static inline BaseInputPin *impl_BaseInputPin_from_IPin( IPin *iface )
     return CONTAINING_RECORD(iface, BaseInputPin, pin.IPin_iface);
 }
 
-static inline BaseInputPin *impl_BaseInputPin_from_BasePin( BasePin *iface )
-{
-    return CONTAINING_RECORD(iface, BaseInputPin, pin);
-}
-
 HRESULT WINAPI BaseInputPinImpl_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
 {
     BaseInputPin *This = impl_BaseInputPin_from_IPin(iface);
@@ -1050,28 +1021,6 @@ HRESULT WINAPI BaseInputPinImpl_NewSegment(IPin * iface, REFERENCE_TIME tStart,
     return SendFurther( iface, deliver_newsegment, &args, NULL );
 }
 
-static const IPinVtbl InputPin_Vtbl =
-{
-    BaseInputPinImpl_QueryInterface,
-    BasePinImpl_AddRef,
-    BaseInputPinImpl_Release,
-    BaseInputPinImpl_Connect,
-    BaseInputPinImpl_ReceiveConnection,
-    BasePinImpl_Disconnect,
-    BasePinImpl_ConnectedTo,
-    BasePinImpl_ConnectionMediaType,
-    BasePinImpl_QueryPinInfo,
-    BasePinImpl_QueryDirection,
-    BasePinImpl_QueryId,
-    BaseInputPinImpl_QueryAccept,
-    BasePinImpl_EnumMediaTypes,
-    BasePinImpl_QueryInternalConnections,
-    BaseInputPinImpl_EndOfStream,
-    BaseInputPinImpl_BeginFlush,
-    BaseInputPinImpl_EndFlush,
-    BaseInputPinImpl_NewSegment
-};
-
 /*** IMemInputPin implementation ***/
 
 static inline BaseInputPin *impl_from_IMemInputPin( IMemInputPin *iface )
index dc59bb9..2b08497 100644 (file)
@@ -24,7 +24,6 @@
 static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
 static const WCHAR wcsOutputPinName[] = {'o','u','t','p','u','t',' ','p','i','n',0};
 
-static const IBaseFilterVtbl TransformFilter_Vtbl;
 static const IPinVtbl TransformFilter_InputPin_Vtbl;
 static const IPinVtbl TransformFilter_OutputPin_Vtbl;
 static const IQualityControlVtbl TransformFilter_QualityControl_Vtbl;
@@ -421,25 +420,6 @@ HRESULT WINAPI TransformFilterImpl_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin
     return E_NOTIMPL;
 }
 
-static const IBaseFilterVtbl TransformFilter_Vtbl =
-{
-    TransformFilterImpl_QueryInterface,
-    BaseFilterImpl_AddRef,
-    TransformFilterImpl_Release,
-    BaseFilterImpl_GetClassID,
-    TransformFilterImpl_Stop,
-    TransformFilterImpl_Pause,
-    TransformFilterImpl_Run,
-    BaseFilterImpl_GetState,
-    BaseFilterImpl_SetSyncSource,
-    BaseFilterImpl_GetSyncSource,
-    BaseFilterImpl_EnumPins,
-    TransformFilterImpl_FindPin,
-    BaseFilterImpl_QueryFilterInfo,
-    BaseFilterImpl_JoinFilterGraph,
-    BaseFilterImpl_QueryVendorInfo
-};
-
 static HRESULT WINAPI TransformFilter_InputPin_EndOfStream(IPin * iface)
 {
     BaseInputPin* This = impl_BaseInputPin_from_IPin(iface);
index 23c0c56..7563a50 100644 (file)
 
 #include "rosip.h"
 
-static const char * const tcp_state_str[] = {
-  "CLOSED",      
-  "LISTEN",      
-  "SYN_SENT",    
-  "SYN_RCVD",    
-  "ESTABLISHED", 
-  "FIN_WAIT_1",  
-  "FIN_WAIT_2",  
-  "CLOSE_WAIT",  
-  "CLOSING",     
-  "LAST_ACK",    
-  "TIME_WAIT"   
-};
-
 extern NPAGED_LOOKASIDE_LIST TdiBucketLookasideList;
 
 static
index 886d6a2..e00fca3 100644 (file)
@@ -1644,7 +1644,7 @@ MMixerSetupFilter(
     IN LPMIXER_DATA MixerData,
     IN PULONG DeviceCount)
 {
-    MIXER_STATUS Status;
+    MIXER_STATUS Status = MM_STATUS_SUCCESS;
     PTOPOLOGY Topology;
     ULONG NodeIndex;
     LPMIXER_INFO MixerInfo = NULL;
index f922970..afe1a22 100644 (file)
@@ -72,7 +72,7 @@ MMixerAddMidiPin(
     MidiInfo->PinId = PinId;
 
     /* sanity check */
-    ASSERT(wcslen(DeviceName) + 1 < MAXPNAMELEN);
+    ASSERT(!DeviceName || (wcslen(DeviceName) + 1 < MAXPNAMELEN));
 
     /* copy device name */
     if (bInput && DeviceName)
index bc9cf07..a9e2944 100644 (file)
@@ -328,7 +328,7 @@ MMixerGetLineControls(
 
     if (MixerLineControls->cbmxctrl != sizeof(MIXERCONTROLW))
     {
-        DPRINT1("Invalid MixerLineControls cbmxctrl passed %lu expected %lu\n", MixerLineControls->cbStruct, sizeof(MIXERLINECONTROLSW));
+        DPRINT1("Invalid MixerLineControls cbmxctrl passed %lu expected %lu\n", MixerLineControls->cbmxctrl, sizeof(MIXERCONTROLW));
         /* invalid parameter */
         return MM_STATUS_INVALID_PARAMETER;
     }
index 03378c2..1e9311a 100644 (file)
@@ -55,7 +55,7 @@ Fast486ReadMemory(PFAST486_STATE State,
     }
 
     /* Check for protected mode */
-    if (State->ControlRegisters[0] & FAST486_CR0_PE)
+    if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
     {
         /* Privilege checks */
 
@@ -122,7 +122,7 @@ Fast486WriteMemory(PFAST486_STATE State,
     }
 
     /* Check for protected mode */
-    if (State->ControlRegisters[0] & FAST486_CR0_PE)
+    if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
     {
         /* Privilege checks */
 
index 57bf933..4990172 100644 (file)
@@ -762,7 +762,7 @@ Fast486ParseModRegRm(PFAST486_STATE State,
     ModRegRm->Register = (ModRmByte >> 3) & 0x07;
 
     /* Check the mode */
-    if ((ModRmByte >> 6) == 3)
+    if (Mode == 3)
     {
         /* The second operand is also a register */
         ModRegRm->Memory = FALSE;
@@ -886,7 +886,6 @@ Fast486ParseModRegRm(PFAST486_STATE State,
                 /* [BX + SI] */
                 ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBX].LowWord
                                            + State->GeneralRegs[FAST486_REG_ESI].LowWord;
-
                 break;
             }
 
@@ -895,7 +894,6 @@ Fast486ParseModRegRm(PFAST486_STATE State,
                 /* [BX + DI] */
                 ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBX].LowWord
                                            + State->GeneralRegs[FAST486_REG_EDI].LowWord;
-
                 break;
             }
 
@@ -904,7 +902,6 @@ Fast486ParseModRegRm(PFAST486_STATE State,
                 /* SS:[BP + SI] */
                 ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBP].LowWord
                                            + State->GeneralRegs[FAST486_REG_ESI].LowWord;
-
                 break;
             }
 
@@ -913,7 +910,6 @@ Fast486ParseModRegRm(PFAST486_STATE State,
                 /* SS:[BP + DI] */
                 ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBP].LowWord
                                            + State->GeneralRegs[FAST486_REG_EDI].LowWord;
-
                 break;
             }
 
@@ -921,7 +917,6 @@ Fast486ParseModRegRm(PFAST486_STATE State,
             {
                 /* [SI] */
                 ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_ESI].LowWord;
-
                 break;
             }
 
@@ -929,7 +924,6 @@ Fast486ParseModRegRm(PFAST486_STATE State,
             {
                 /* [DI] */
                 ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EDI].LowWord;
-
                 break;
             }
 
@@ -953,7 +947,6 @@ Fast486ParseModRegRm(PFAST486_STATE State,
             {
                 /* [BX] */
                 ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBX].LowWord;
-
                 break;
             }
         }
index 9af5b96..974e99b 100644 (file)
@@ -137,7 +137,7 @@ Fast486DumpState(PFAST486_STATE State)
 {
     DbgPrint("\nFast486DumpState -->\n");
     DbgPrint("\nCPU currently executing in %s mode at %04X:%08X\n",
-            (State->ControlRegisters[0] & FAST486_CR0_PE) ? "protected" : "real",
+            (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) ? "protected" : "real",
              State->SegmentRegs[FAST486_REG_CS].Selector,
              State->InstPtr.Long);
     DbgPrint("\nGeneral purpose registers:\n"
index 12670a4..38dfc3f 100644 (file)
@@ -37,8 +37,8 @@
 FAST486_OPCODE_HANDLER_PROC
 Fast486ExtendedHandlers[FAST486_NUM_OPCODE_HANDLERS] =
 {
-    Fast486OpcodeGroup0F00,             /* 0x00 - 0x01 */
-    Fast486OpcodeGroup0F01,
+    Fast486ExtOpcodeGroup0F00,          /* 0x00 - 0x01 */
+    Fast486ExtOpcodeGroup0F01,
     Fast486ExtOpcodeLar,                /* 0x02 */
     Fast486ExtOpcodeLsl,                /* 0x03 */
     Fast486ExtOpcodeInvalid,            /* 0x04 - 0x05 */   // Invalid
@@ -222,8 +222,8 @@ Fast486ExtendedHandlers[FAST486_NUM_OPCODE_HANDLERS] =
     Fast486ExtOpcodeMovzxByte,          /* 0xB6 - 0xB7 */
     Fast486ExtOpcodeMovzxWord,
     Fast486ExtOpcodeInvalid,            /* 0xB8 */          // Invalid
-    Fast486OpcodeGroup0FB9,             /* 0xB9 */
-    Fast486OpcodeGroup0FBA,             /* 0xBA */
+    Fast486ExtOpcodeGroup0FB9,          /* 0xB9 */
+    Fast486ExtOpcodeGroup0FBA,          /* 0xBA */
     Fast486ExtOpcodeBtc,                /* 0xBB */
     Fast486ExtOpcodeBsf,                /* 0xBC */
     Fast486ExtOpcodeBsr,                /* 0xBD */
index 9df60e5..6bfd382 100644 (file)
@@ -54,9 +54,9 @@ Fast486ExecutionControl(PFAST486_STATE State, FAST486_EXEC_CMD Command)
     /* Main execution loop */
     do
     {
-NextInst:
         if (!State->Halted)
         {
+NextInst:
             /* Check if this is a new instruction */
             if (State->PrefixFlags == 0) State->SavedInstPtr = State->InstPtr;
 
index cadbd54..06b3f9e 100644 (file)
@@ -4985,8 +4985,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeLoop)
         /* Additional rule for LOOPNZ */
         if (State->Flags.Zf) Condition = FALSE;
     }
-
-    if (Opcode == 0xE1)
+    else if (Opcode == 0xE1)
     {
         /* Additional rule for LOOPZ */
         if (!State->Flags.Zf) Condition = FALSE;
index 5ec066b..303fcd1 100644 (file)
@@ -1703,7 +1703,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
     return TRUE;
 }
 
-FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F00)
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F00)
 {
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
@@ -2014,7 +2015,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F00)
     }
 }
 
-FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F01)
 {
     // FAST486_TABLE_REG TableReg;
     UCHAR TableReg[6];
@@ -2230,7 +2231,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
     }
 }
 
-FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FB9)
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0FB9)
 {
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
@@ -2248,7 +2249,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FB9)
     return FALSE;
 }
 
-FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FBA)
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0FBA)
 {
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN OperandSize, AddressSize;
index f74877d..38eed67 100644 (file)
@@ -42,10 +42,11 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6);
 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7);
 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFE);
 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF);
-FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F00);
-FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01);
-FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FB9);
-FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FBA);
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F00);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F01);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0FB9);
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0FBA);
 
 #endif // _OPGROUPS_H_
 
index c7aa880..ddb6b15 100644 (file)
@@ -362,8 +362,11 @@ RtlClearBits(
 
     /* Clear what's left */
     NumberToClear &= (_BITCOUNT - 1);
-    Mask = MAXINDEX << NumberToClear;
-    *Buffer &= Mask;
+    if (NumberToClear)
+    {
+        Mask = MAXINDEX << NumberToClear;
+        *Buffer &= Mask;
+    }
 }
 
 VOID
@@ -419,8 +422,11 @@ RtlSetBits(
 
     /* Set what's left */
     NumberToSet &= (_BITCOUNT - 1);
-    Mask = MAXINDEX << NumberToSet;
-    *Buffer |= ~Mask;
+    if (NumberToSet)
+    {
+        Mask = MAXINDEX << NumberToSet;
+        *Buffer |= ~Mask;
+    }
 }
 
 BOOLEAN
index 8edeb3a..e034f34 100644 (file)
@@ -269,10 +269,10 @@ kernel32 -
   reactos/dll/win32/kernel32/wine/lzexpand.c             # Synced in r52754
   reactos/dll/win32/kernel32/wine/profile.c              # Synced in r52754
   reactos/dll/win32/kernel32/wine/res.c                  # Synced in r52754
-  reactos/dll/win32/kernel32/winnls/string/casemap.c     # Synced in r52754
+  reactos/dll/win32/kernel32/winnls/string/casemap.c     # Synced to Wine-1.7.27
   reactos/dll/win32/kernel32/winnls/string/chartype.c    # Synced in r52754
   reactos/dll/win32/kernel32/winnls/string/collation.c   # Synced in r52754
-  reactos/dll/win32/kernel32/winnls/string/format_msg.c  # Synced to Wine-1.5.4
+  reactos/dll/win32/kernel32/winnls/string/format_msg.c  # Synced to Wine-1.7.27
   reactos/dll/win32/kernel32/winnls/string/lang.c        # Synced in r52754
   reactos/dll/win32/kernel32/winnls/string/lcformat.c    # Synced in r52754
   reactos/dll/win32/kernel32/winnls/string/nls.c         # Synced in r52754
index 219c0b4..0eeccc4 100644 (file)
@@ -719,7 +719,7 @@ MmPageFault(
 
 VOID
 NTAPI
-MiInitializeSpecialPool();
+MiInitializeSpecialPool(VOID);
 
 BOOLEAN
 NTAPI
@@ -732,6 +732,11 @@ NTAPI
 MmIsSpecialPoolAddress(
     IN PVOID P);
 
+BOOLEAN
+NTAPI
+MmIsSpecialPoolAddressFree(
+    IN PVOID P);
+
 PVOID
 NTAPI
 MmAllocateSpecialPool(
index 820201f..d0a3f3a 100644 (file)
@@ -975,15 +975,31 @@ KeBugCheckWithTf(IN ULONG BugCheckCode,
                                               FALSE,
                                               &IsSystem);
             }
+            else
+            {
+                /* Can't blame a driver, assume system */
+                IsSystem = TRUE;
+            }
 
-            /*
-             * Now we should check if this happened in:
-             * 1) Special Pool 2) Free Special Pool 3) Session Pool
-             * and update the bugcheck code appropriately.
-             */
+            /* FIXME: Check for session pool in addition to special pool */
 
-            /* Check if we didn't have a driver base */
-            if (!DriverBase)
+            /* Special pool has its own bug check codes */
+            if (MmIsSpecialPoolAddress((PVOID)BugCheckParameter1))
+            {
+                if (MmIsSpecialPoolAddressFree((PVOID)BugCheckParameter1))
+                {
+                    KiBugCheckData[0] = IsSystem
+                        ? PAGE_FAULT_IN_FREED_SPECIAL_POOL
+                        : DRIVER_PAGE_FAULT_IN_FREED_SPECIAL_POOL;
+                }
+                else
+                {
+                    KiBugCheckData[0] = IsSystem
+                        ? PAGE_FAULT_BEYOND_END_OF_ALLOCATION
+                        : DRIVER_PAGE_FAULT_BEYOND_END_OF_ALLOCATION;
+                }
+            }
+            else if (!DriverBase)
             {
                 /* Find the driver that unloaded at this address */
                 KiBugCheckDriver = NULL; // FIXME: ROS can't locate
index 68063b2..b9e4c3a 100644 (file)
@@ -932,7 +932,7 @@ InitializePool(IN POOL_TYPE PoolType,
         }
 
         //
-        // Finally, add one entry, compute the hash, and zero the table
+        // Add one entry, compute the hash, and zero the table
         //
         PoolTrackTableSize++;
         PoolTrackTableMask = PoolTrackTableSize - 2;
@@ -940,6 +940,11 @@ InitializePool(IN POOL_TYPE PoolType,
         RtlZeroMemory(PoolTrackTable,
                       PoolTrackTableSize * sizeof(POOL_TRACKER_TABLE));
 
+        //
+        // Finally, add the most used tags to speed up those allocations
+        //
+        ExpSeedHotTags();
+
         //
         // We now do the exact same thing with the tracker table for big pages
         //
@@ -2041,10 +2046,25 @@ NTAPI
 ExAllocatePool(POOL_TYPE PoolType,
                SIZE_T NumberOfBytes)
 {
-    //
-    // Use a default tag of "None"
-    //
-    return ExAllocatePoolWithTag(PoolType, NumberOfBytes, TAG_NONE);
+    ULONG Tag = TAG_NONE;
+#if 0 && DBG
+    PLDR_DATA_TABLE_ENTRY LdrEntry;
+
+    /* Use the first four letters of the driver name, or "None" if unavailable */
+    LdrEntry = KeGetCurrentIrql() <= APC_LEVEL
+                ? MiLookupDataTableEntry(_ReturnAddress())
+                : NULL;
+    if (LdrEntry)
+    {
+        ULONG i;
+        Tag = 0;
+        for (i = 0; i < min(4, LdrEntry->BaseDllName.Length / sizeof(WCHAR)); i++)
+            Tag = Tag >> 8 | (LdrEntry->BaseDllName.Buffer[i] & 0xff) << 24;
+        for (; i < 4; i++)
+            Tag = Tag >> 8 | ' ' << 24;
+    }
+#endif
+    return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
 }
 
 /*
@@ -2508,7 +2528,7 @@ ExAllocatePoolWithQuota(IN POOL_TYPE PoolType,
     //
     // Allocate the pool
     //
-    return ExAllocatePoolWithQuotaTag(PoolType, NumberOfBytes, 'enoN');
+    return ExAllocatePoolWithQuotaTag(PoolType, NumberOfBytes, TAG_NONE);
 }
 
 /*
index ffe6f6a..8b20e2f 100644 (file)
@@ -935,15 +935,15 @@ MiResolveTransitionFault(IN PVOID FaultingAddress,
     /* See if we should wait before terminating the fault */
     if (Pfn1->u3.e1.ReadInProgress == 1)
     {
-       DPRINT1("The page is currently being read!\n");
-       ASSERT(Pfn1->u1.Event != NULL);
-       *InPageBlock = Pfn1->u1.Event;
-       if (PointerPte == Pfn1->PteAddress)
-       {
-           DPRINT1("And this if for this particular PTE.\n");
-           /* The PTE will be made valid by the thread serving the fault */
-           return STATUS_SUCCESS; // FIXME: Maybe something more descriptive
-       }
+        DPRINT1("The page is currently being read!\n");
+        ASSERT(Pfn1->u1.Event != NULL);
+        *InPageBlock = Pfn1->u1.Event;
+        if (PointerPte == Pfn1->PteAddress)
+        {
+            DPRINT1("And this if for this particular PTE.\n");
+            /* The PTE will be made valid by the thread serving the fault */
+            return STATUS_SUCCESS; // FIXME: Maybe something more descriptive
+        }
     }
 
     /* Windows checks there's some free pages and this isn't an in-page error */
@@ -1424,8 +1424,8 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
 
         if (InPageBlock != NULL)
         {
-               /* The page is being paged in by another process */
-               KeWaitForSingleObject(InPageBlock, WrPageIn, KernelMode, FALSE, NULL);
+            /* The page is being paged in by another process */
+            KeWaitForSingleObject(InPageBlock, WrPageIn, KernelMode, FALSE, NULL);
         }
 
         ASSERT(OldIrql == KeGetCurrentIrql());
@@ -1833,6 +1833,17 @@ _WARN("Session space stuff is not implemented yet!")
                              (ULONG_PTR)TrapInformation,
                              1);
             }
+
+            /* Check for no protecton at all */
+            if (TempPte.u.Soft.Protection == MM_ZERO_ACCESS)
+            {
+                /* Bugcheck the system! */
+                KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
+                             (ULONG_PTR)Address,
+                             StoreInstruction,
+                             (ULONG_PTR)TrapInformation,
+                             0);
+            }
         }
 
         /* Check for demand page */
index 49e6055..0cdf5da 100644 (file)
@@ -20,6 +20,7 @@
 #define MODULE_INVOLVED_IN_ARM3
 #include "../ARM3/miarm.h"
 
+extern ULONG ExpPoolFlags;
 extern PMMPTE MmSystemPteBase;
 
 PMMPTE
@@ -73,22 +74,40 @@ MmUseSpecialPool(SIZE_T NumberOfBytes, ULONG Tag)
     if (NumberOfBytes > (PAGE_SIZE - sizeof(POOL_HEADER)))
         return FALSE;
 
-    // FIXME
-    //return TRUE;
-    return FALSE;
+    return Tag == MmSpecialPoolTag;
 }
 
 BOOLEAN
 NTAPI
 MmIsSpecialPoolAddress(PVOID P)
 {
-    return((P >= MmSpecialPoolStart) &&
-           (P <= MmSpecialPoolEnd));
+    return ((P >= MmSpecialPoolStart) &&
+            (P <= MmSpecialPoolEnd));
+}
+
+BOOLEAN
+NTAPI
+MmIsSpecialPoolAddressFree(PVOID P)
+{
+    PMMPTE PointerPte;
+
+    ASSERT(MmIsSpecialPoolAddress(P));
+    PointerPte = MiAddressToPte(P);
+
+    if (PointerPte->u.Soft.PageFileHigh == SPECIAL_POOL_PAGED_PTE ||
+        PointerPte->u.Soft.PageFileHigh == SPECIAL_POOL_NONPAGED_PTE)
+    {
+        /* Guard page PTE */
+        return FALSE;
+    }
+
+    /* Free PTE */
+    return TRUE;
 }
 
 VOID
 NTAPI
-MiInitializeSpecialPool()
+MiInitializeSpecialPool(VOID)
 {
     ULONG SpecialPoolPtes, i;
     PMMPTE PointerPte;
@@ -98,7 +117,7 @@ MiInitializeSpecialPool()
         (MmSpecialPoolTag == -1)) return;
 
     /* Calculate number of system PTEs for the special pool */
-    if ( MmNumberOfSystemPtes >= 0x3000 )
+    if (MmNumberOfSystemPtes >= 0x3000)
         SpecialPoolPtes = MmNumberOfSystemPtes / 3;
     else
         SpecialPoolPtes = MmNumberOfSystemPtes / 6;
@@ -119,7 +138,7 @@ MiInitializeSpecialPool()
 
         /* Reserving didn't work, so try to reduce the requested size */
         ASSERT(SpecialPoolPtes >= PTE_PER_PAGE);
-        SpecialPoolPtes -= 1024;
+        SpecialPoolPtes -= PTE_PER_PAGE;
     } while (SpecialPoolPtes);
 
     /* Fail if we couldn't reserve them at all */
@@ -132,7 +151,7 @@ MiInitializeSpecialPool()
     MiSpecialPoolFirstPte = PointerPte;
     MmSpecialPoolStart = MiPteToAddress(PointerPte);
 
-    for (i = 0; i<512; i++)
+    for (i = 0; i < PTE_PER_PAGE / 2; i++)
     {
         /* Point it to the next entry */
         PointerPte->u.List.NextEntry = &PointerPte[2] - MmSystemPteBase;
@@ -143,7 +162,7 @@ MiInitializeSpecialPool()
 
     /* Save extra values */
     MiSpecialPoolExtra = PointerPte;
-    MiSpecialPoolExtraCount = SpecialPoolPtes - 1024;
+    MiSpecialPoolExtraCount = SpecialPoolPtes - PTE_PER_PAGE;
 
     /* Mark the previous PTE as the last one */
     MiSpecialPoolLastPte = PointerPte - 2;
@@ -160,10 +179,52 @@ MiInitializeSpecialPool()
         MiSpecialPagesNonPagedMaximum = MmResidentAvailablePages >> 3;
 
     DPRINT1("Special pool start %p - end %p\n", MmSpecialPoolStart, MmSpecialPoolEnd);
+    ExpPoolFlags |= POOL_FLAG_SPECIAL_POOL;
 
     //MiTestSpecialPool();
 }
 
+NTSTATUS
+NTAPI
+MmExpandSpecialPool(VOID)
+{
+    ULONG i;
+    PMMPTE PointerPte;
+
+    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+    if (MiSpecialPoolExtraCount == 0)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    PointerPte = MiSpecialPoolExtra;
+    ASSERT(MiSpecialPoolFirstPte == MiSpecialPoolLastPte);
+    ASSERT(MiSpecialPoolFirstPte->u.List.NextEntry == MM_EMPTY_PTE_LIST);
+    MiSpecialPoolFirstPte->u.List.NextEntry = PointerPte - MmSystemPteBase;
+
+    ASSERT(MiSpecialPoolExtraCount >= PTE_PER_PAGE);
+    for (i = 0; i < PTE_PER_PAGE / 2; i++)
+    {
+        /* Point it to the next entry */
+        PointerPte->u.List.NextEntry = &PointerPte[2] - MmSystemPteBase;
+
+        /* Move to the next pair */
+        PointerPte += 2;
+    }
+
+    /* Save remaining extra values */
+    MiSpecialPoolExtra = PointerPte;
+    MiSpecialPoolExtraCount -= PTE_PER_PAGE;
+
+    /* Mark the previous PTE as the last one */
+    MiSpecialPoolLastPte = PointerPte - 2;
+    MiSpecialPoolLastPte->u.List.NextEntry = MM_EMPTY_PTE_LIST;
+
+    /* Save new end address of the special pool */
+    MmSpecialPoolEnd = MiPteToAddress(MiSpecialPoolLastPte + 1);
+
+    return STATUS_SUCCESS;
+}
+
 PVOID
 NTAPI
 MmAllocateSpecialPool(SIZE_T NumberOfBytes, ULONG Tag, POOL_TYPE PoolType, ULONG SpecialType)
@@ -176,7 +237,7 @@ MmAllocateSpecialPool(SIZE_T NumberOfBytes, ULONG Tag, POOL_TYPE PoolType, ULONG
     PVOID Entry;
     PPOOL_HEADER Header;
 
-    DPRINT1("MmAllocateSpecialPool(%x %x %x %x)\n", NumberOfBytes, Tag, PoolType, SpecialType);
+    DPRINT("MmAllocateSpecialPool(%x %x %x %x)\n", NumberOfBytes, Tag, PoolType, SpecialType);
 
     /* Check if the pool is initialized and quit if it's not */
     if (!MiSpecialPoolFirstPte) return NULL;
@@ -191,7 +252,11 @@ MmAllocateSpecialPool(SIZE_T NumberOfBytes, ULONG Tag, POOL_TYPE PoolType, ULONG
         ((PoolType != PagedPool) && (Irql > DISPATCH_LEVEL)))
     {
         /* Bad caller */
-        KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION, Irql, PoolType, NumberOfBytes, 0x30);
+        KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
+                     Irql,
+                     PoolType,
+                     NumberOfBytes,
+                     0x30);
     }
 
     /* TODO: Take into account various limitations */
@@ -210,14 +275,19 @@ MmAllocateSpecialPool(SIZE_T NumberOfBytes, ULONG Tag, POOL_TYPE PoolType, ULONG
         return NULL;
     }
 
-    /* Reject allocation if special pool PTE list is exhausted */
+    /* Check if special pool PTE list is exhausted */
     if (MiSpecialPoolFirstPte->u.List.NextEntry == MM_EMPTY_PTE_LIST)
     {
-        /* Release the PFN database lock */
-        KeReleaseQueuedSpinLock(LockQueuePfnLock, Irql);
-        DPRINT1("Special pool: No PTEs left!\n");
-        /* TODO: Expand the special pool */
-        return NULL;
+        /* Try to expand it */
+        if (!NT_SUCCESS(MmExpandSpecialPool()))
+        {
+            /* No reserves left, reject this allocation */
+            static int once;
+            KeReleaseQueuedSpinLock(LockQueuePfnLock, Irql);
+            if (!once++) DPRINT1("Special pool: No PTEs left!\n");
+            return NULL;
+        }
+        ASSERT(MiSpecialPoolFirstPte->u.List.NextEntry != MM_EMPTY_PTE_LIST);
     }
 
     /* Save allocation time */
@@ -286,8 +356,8 @@ MmAllocateSpecialPool(SIZE_T NumberOfBytes, ULONG Tag, POOL_TYPE PoolType, ULONG
        That time will be used to check memory consistency within the allocated
        page. */
     Header->PoolTag = Tag;
-    Header->BlockSize = (USHORT)TickCount.LowPart;
-    DPRINT1("%p\n", Entry);
+    Header->BlockSize = (UCHAR)TickCount.LowPart;
+    DPRINT("%p\n", Entry);
     return Entry;
 }
 
@@ -300,6 +370,7 @@ MiSpecialPoolCheckPattern(PUCHAR P, PPOOL_HEADER Header)
 
     /* Get amount of bytes user requested to be allocated by clearing out the paged mask */
     BytesRequested = (Header->Ulong1 & ~SPECIAL_POOL_PAGED) & 0xFFFF;
+    ASSERT(BytesRequested <= PAGE_SIZE - sizeof(POOL_HEADER));
 
     /* Get a pointer to the end of user's area */
     Ptr = P + BytesRequested;
@@ -320,7 +391,11 @@ MiSpecialPoolCheckPattern(PUCHAR P, PPOOL_HEADER Header)
         /* Bugcheck if bytes don't match */
         if (Ptr[Index] != Header->BlockSize)
         {
-            KeBugCheckEx(BAD_POOL_HEADER, (ULONG_PTR)P, (ULONG_PTR)&Ptr[Index], Header->BlockSize, 0x24);
+            KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
+                         (ULONG_PTR)P,
+                         (ULONG_PTR)&Ptr[Index],
+                         Header->BlockSize,
+                         0x24);
         }
     }
 }
@@ -341,7 +416,7 @@ MmFreeSpecialPool(PVOID P)
     LARGE_INTEGER TickCount;
     PMMPFN Pfn;
 
-    DPRINT1("MmFreeSpecialPool(%p)\n", P);
+    DPRINT("MmFreeSpecialPool(%p)\n", P);
 
     /* Get the PTE */
     PointerPte = MiAddressToPte(P);
@@ -353,7 +428,11 @@ MmFreeSpecialPool(PVOID P)
         if (PointerPte->u.Soft.Protection == MM_NOACCESS ||
             !PointerPte->u.Soft.Protection)
         {
-            KeBugCheckEx(BAD_POOL_HEADER, (ULONG_PTR)P, (ULONG_PTR)PointerPte, 0, 0x20);
+            KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
+                         (ULONG_PTR)P,
+                         (ULONG_PTR)PointerPte,
+                         0,
+                         0x20);
         }
     }
 
@@ -375,28 +454,35 @@ MmFreeSpecialPool(PVOID P)
     if ((Header->Ulong1 & SPECIAL_POOL_PAGED) == 0)
     {
         /* Non-paged allocation, ensure that IRQ is not higher that DISPATCH */
-        ASSERT((PointerPte + 1)->u.Soft.PageFileHigh == SPECIAL_POOL_NONPAGED_PTE);
+        PoolType = NonPagedPool;
+        ASSERT(PointerPte[1].u.Soft.PageFileHigh == SPECIAL_POOL_NONPAGED_PTE);
         if (Irql > DISPATCH_LEVEL)
         {
-            KeBugCheckEx(BAD_POOL_HEADER, Irql, (ULONG_PTR)P, 0, 0x31);
+            KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
+                         Irql,
+                         PoolType,
+                         (ULONG_PTR)P,
+                         0x31);
         }
-
-        PoolType = NonPagedPool;
     }
     else
     {
         /* Paged allocation, ensure */
-        ASSERT((PointerPte + 1)->u.Soft.PageFileHigh == SPECIAL_POOL_PAGED_PTE);
-        if (Irql > DISPATCH_LEVEL)
+        PoolType = PagedPool;
+        ASSERT(PointerPte[1].u.Soft.PageFileHigh == SPECIAL_POOL_PAGED_PTE);
+        if (Irql > APC_LEVEL)
         {
-            KeBugCheckEx(BAD_POOL_HEADER, Irql, (ULONG_PTR)P, 1, 0x31);
+            KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
+                         Irql,
+                         PoolType,
+                         (ULONG_PTR)P,
+                         0x31);
         }
-
-        PoolType = PagedPool;
     }
 
     /* Get amount of bytes user requested to be allocated by clearing out the paged mask */
     BytesRequested = (Header->Ulong1 & ~SPECIAL_POOL_PAGED) & 0xFFFF;
+    ASSERT(BytesRequested <= PAGE_SIZE - sizeof(POOL_HEADER));
 
     /* Check memory before the allocated user buffer in case of overruns detection */
     if (Overruns)
@@ -407,21 +493,33 @@ MmFreeSpecialPool(PVOID P)
         /* If they mismatch, it's unrecoverable */
         if (BytesRequested > BytesReal)
         {
-            KeBugCheckEx(BAD_POOL_HEADER, (ULONG_PTR)P, BytesRequested, BytesReal, 0x21);
+            KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
+                         (ULONG_PTR)P,
+                         BytesRequested,
+                         BytesReal,
+                         0x21);
         }
 
         if (BytesRequested + sizeof(POOL_HEADER) < BytesReal)
         {
-            KeBugCheckEx(BAD_POOL_HEADER, (ULONG_PTR)P, BytesRequested, BytesReal, 0x22);
+            KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
+                         (ULONG_PTR)P,
+                         BytesRequested,
+                         BytesReal,
+                         0x22);
         }
 
         /* Actually check the memory pattern */
         for (b = (PUCHAR)(Header + 1); b < (PUCHAR)P; b++)
         {
-            if (Header->BlockSize != b[0])
+            if (*b != Header->BlockSize)
             {
                 /* Bytes mismatch */
-                KeBugCheckEx(BAD_POOL_HEADER, (ULONG_PTR)P, (ULONG_PTR)b, Header->BlockSize, 0x23);
+                KeBugCheckEx(SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION,
+                             (ULONG_PTR)P,
+                             (ULONG_PTR)b,
+                             Header->BlockSize,
+                             0x23);
             }
         }
     }
@@ -448,7 +546,6 @@ MmFreeSpecialPool(PVOID P)
         Pfn = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
 
         /* Lock PFN database */
-        ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
         Irql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
 
         /* Delete this PFN */
@@ -457,6 +554,8 @@ MmFreeSpecialPool(PVOID P)
         /* Decrement share count of this PFN */
         MiDecrementShareCount(Pfn, PointerPte->u.Hard.PageFrameNumber);
 
+        MI_ERASE_PTE(PointerPte);
+
         /* Flush the TLB */
         //FIXME: Use KeFlushSingleTb() instead
         KeFlushEntireTb(TRUE, TRUE);
@@ -467,12 +566,11 @@ MmFreeSpecialPool(PVOID P)
         MiDeleteSystemPageableVm(PointerPte, 1, 0, NULL);
 
         /* Lock PFN database */
-        ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
         Irql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
     }
 
     /* Mark next PTE as invalid */
-    PointerPte[1].u.Long = 0; //|= 8000;
+    MI_ERASE_PTE(PointerPte + 1);
 
     /* Make sure that the last entry is really the last one */
     ASSERT(MiSpecialPoolLastPte->u.List.NextEntry == MM_EMPTY_PTE_LIST);
index 86bd226..e87db2e 100644 (file)
@@ -49,8 +49,7 @@ static BYTE Int16To32[] =
 
     0xFB,               // sti
 
-    // HACK: The following instruction should be HLT!
-    0x90,               // nop
+    0xF4,               // hlt
 
     0xEB, 0xF5,         // jmp BOP_SEQ (offset -11)
 
index 2a74018..16648a1 100644 (file)
@@ -59,7 +59,7 @@ IntCopyRegistryKey(
             if (InfoBuffer == NULL)
             {
                 ERR_(VIDEOPRT, "Could not allocate buffer for key info\n");
-                return Status;
+                return STATUS_INSUFFICIENT_RESOURCES;
             }
         }
 
index e47bdaf..2fe405f 100644 (file)
@@ -2083,7 +2083,7 @@ ftGdiGetGlyphOutline(
                 src += ft_face->glyph->bitmap.pitch;
                 dst += pitch;
             }
-            return needed;
+            break;
         }
         case ft_glyph_format_outline:
         {
@@ -2113,22 +2113,24 @@ ftGdiGetGlyphOutline(
             {
                 return GDI_ERROR;
             }
+
+            start = pvBuf;
+            for (row = 0; row < height; row++)
+            {
+                ptr = start;
+                for (col = 0; col < width; col++, ptr++)
+                {
+                    *ptr = (((int)*ptr) * mult + 128) / 256;
+                }
+                start += pitch;
+            }
+
+            break;
         }
         default:
             DPRINT1("Loaded glyph format %x\n", ft_face->glyph->format);
             return GDI_ERROR;
         }
-        start = pvBuf;
-        for (row = 0; row < height; row++)
-        {
-            ptr = start;
-            for (col = 0; col < width; col++, ptr++)
-            {
-                *ptr = (((int)*ptr) * mult + 128) / 256;
-            }
-            start += pitch;
-        }
-        break;
     }
 
     case GGO_NATIVE:
index 3684f40..6fba126 100644 (file)
@@ -162,15 +162,3 @@ BOOL NTAPI W32kDosPathNameToNtPathName(PCWSTR, PUNICODE_STRING);
 
 #define ROUND_UP(n, align) \
     ROUND_DOWN(((ULONG)n) + (align) - 1, (align))
-
-#define LIST_FOR_EACH(elem, list, type, field) \
-    for ((elem) = CONTAINING_RECORD((list)->Flink, type, field); \
-         &(elem)->field != (list) && ((&((elem)->field)) != NULL); \
-         (elem) = CONTAINING_RECORD((elem)->field.Flink, type, field))
-
-#define LIST_FOR_EACH_SAFE(cursor, cursor2, list, type, field) \
-    for ((cursor) = CONTAINING_RECORD((list)->Flink, type, field), \
-         (cursor2) = CONTAINING_RECORD((cursor)->field.Flink, type, field); \
-         &(cursor)->field != (list); \
-         (cursor) = (cursor2), \
-         (cursor2) = CONTAINING_RECORD((cursor)->field.Flink, type, field))
index be60358..c89f852 100644 (file)
@@ -521,18 +521,24 @@ typedef struct _CLS
     INT cbclsExtra;
     INT cbwndExtra;
     HINSTANCE hModule;
+#ifdef NEW_CURSORICON
+    struct _CURICON_OBJECT* spicn;
+    struct _CURICON_OBJECT* spcur;
+#else
     HANDLE hIcon; /* FIXME - Use pointer! */
-    //PCURSOR spicn;
     HANDLE hCursor; /* FIXME - Use pointer! */
-    //PCURSOR spcur;
+#endif
     HBRUSH hbrBackground;
     PWSTR lpszMenuName;     // kernel use
     PSTR lpszAnsiClassName; // "
+#ifdef NEW_CURSORICON
+    struct _CURICON_OBJECT* spicnSm;
+#else
     HANDLE hIconSm; /* FIXME - Use pointer! */
-    //PCURSOR spicnSm;
 
     //// ReactOS dosn't suppot cache icons.
     HICON hIconSmIntern; /* Internal small icon, derived from hIcon */
+#endif
     ////
     UINT Unicode : 1; // !CSF_ANSIPROC
     UINT Global : 1;  // CS_GLOBALCLASS or CSF_SERVERSIDEPROC
index 970f7b2..801000c 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <win32k.h>
+DBG_DEFAULT_CHANNEL(UserClass);
 
 /* CALLPROC ******************************************************************/
 
@@ -110,6 +111,7 @@ UserGetCPD(
 {
    PCLS pCls;
    PWND pWnd;
+   PDESKTOP pDesk;
    PCALLPROCDATA CallProc = NULL;
    PTHREADINFO pti;
 
@@ -131,7 +133,14 @@ UserGetCPD(
    // No luck, create a new one for the requested proc.
    if (!CallProc)
    {
-      CallProc = CreateCallProc( pCls->rpdeskParent,
+      if (!pCls->rpdeskParent)
+      {
+         TRACE("Null DESKTOP Atom %d\n",pCls->atomClassName);
+         pDesk = pti->rpdesk;
+      }
+      else
+         pDesk = pCls->rpdeskParent;
+      CallProc = CreateCallProc( pDesk,
                                  (WNDPROC)ProcIn,
                                  !!(Flags & UserGetCPDA2U),
                                  pti->ppi);
index f14071e..dd95752 100644 (file)
@@ -245,8 +245,17 @@ IntDestroyClass(IN OUT PCLS Class)
         IntFreeClassMenuName(Class);
     }
 
+#ifdef NEW_CURSORICON
+    if (Class->spicn)
+        UserDereferenceObject(Class->spicn);
+    if (Class->spicnSm)
+        UserDereferenceObject(Class->spicnSm);
+    if (Class->spcur)
+        UserDereferenceObject(Class->spcur);
+#else
     if (Class->hIconSmIntern)
         IntClassDestroyIcon(Class->hIconSmIntern);
+#endif
 
     pDesk = Class->rpdeskParent;
     Class->rpdeskParent = NULL;
@@ -587,11 +596,22 @@ IntGetClassForDesktop(IN OUT PCLS BaseClass,
 
         Class = DesktopHeapAlloc(Desktop,
                                  ClassSize);
+
         if (Class != NULL)
         {
             /* Simply clone the class */
             RtlCopyMemory( Class, BaseClass, ClassSize);
 
+#ifdef NEW_CURSORICON
+            /* Reference our objects */
+            if (Class->spcur)
+                UserReferenceObject(Class->spcur);
+            if (Class->spicn)
+                UserReferenceObject(Class->spicn);
+            if (Class->spicnSm)
+                UserReferenceObject(Class->spicnSm);
+#endif
+
             TRACE("Clone Class 0x%p hM 0x%p\n %S\n",Class, Class->hModule, Class->lpszClientUnicodeMenuName);
 
             /* Restore module address if default user class Ref: Bug 4778 */
@@ -1009,10 +1029,15 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
             Class->cbclsExtra = lpwcx->cbClsExtra;
             Class->cbwndExtra = lpwcx->cbWndExtra;
             Class->hModule = lpwcx->hInstance;
-            //// FIXME handles to pointers
+#ifdef NEW_CURSORICON
+            Class->spicn = lpwcx->hIcon ? UserGetCurIconObject(lpwcx->hIcon) : NULL;
+            Class->spcur = lpwcx->hCursor ? UserGetCurIconObject(lpwcx->hCursor) : NULL;
+            Class->spicnSm = lpwcx->hIconSm ? UserGetCurIconObject(lpwcx->hIconSm) : NULL;
+#else
             Class->hIcon = lpwcx->hIcon;
             Class->hIconSm = lpwcx->hIconSm;
             Class->hCursor = lpwcx->hCursor;
+#endif
             ////
             Class->hbrBackground = lpwcx->hbrBackground;
 
@@ -1726,13 +1751,7 @@ IntSetClassMenuName(IN PCLS Class,
     return Ret;
 }
 
-//// Do this for now in anticipation of new cursor icon code.
 #ifndef NEW_CURSORICON
-BOOLEAN FASTCALL IntDestroyCurIconObject(PCURICON_OBJECT, PPROCESSINFO);
-#else
-BOOLEAN FASTCALL IntDestroyCurIconObject(PCURICON_OBJECT, BOOLEAN);
-#endif
-
 BOOL FASTCALL
 IntClassDestroyIcon(HANDLE hCurIcon)
 {
@@ -1745,19 +1764,15 @@ IntClassDestroyIcon(HANDLE hCurIcon)
         ERR("hCurIcon was not found!\n");
         return FALSE;
     }
-#ifndef NEW_CURSORICON
-    Ret = IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process());
     /* Note: IntDestroyCurIconObject will remove our reference for us! */
-#else
-    /* Note: IntDestroyCurIconObject will remove our reference for us! */
-    Ret = IntDestroyCurIconObject(CurIcon, TRUE);
-#endif
+    Ret = IntDestroyCurIconObject(CurIcon, GetW32ProcessInfo());
     if (!Ret)
     {
        ERR("hCurIcon was not Destroyed!\n");
     }
     return Ret;
 }
+#endif
 
 ULONG_PTR
 UserSetClassLongPtr(IN PCLS Class,
@@ -1766,7 +1781,9 @@ UserSetClassLongPtr(IN PCLS Class,
                     IN BOOL Ansi)
 {
     ULONG_PTR Ret = 0;
+#ifndef NEW_CURSORICON
     HANDLE hIconSmIntern = NULL;
+#endif
 
     /* NOTE: For GCLP_MENUNAME and GCW_ATOM this function may raise an exception! */
 
@@ -1838,6 +1855,54 @@ UserSetClassLongPtr(IN PCLS Class,
             }
             break;
 
+#ifdef NEW_CURSORICON
+        case GCLP_HCURSOR:
+        {
+            PCURICON_OBJECT NewCursor = NULL;
+
+            if (NewLong)
+            {
+                NewCursor = UserGetCurIconObject((HCURSOR)NewLong);
+                if (!NewCursor)
+                {
+                    EngSetLastError(ERROR_INVALID_CURSOR_HANDLE);
+                    return 0;
+                }
+            }
+
+            if (Class->spcur)
+            {
+                Ret = (ULONG_PTR)UserHMGetHandle(Class->spcur);
+                UserDereferenceObject(Class->spcur);
+            }
+            else
+            {
+                Ret = 0;
+            }
+
+            if (Ret == NewLong)
+            {
+                /* It's a nop */
+                return Ret;
+            }
+
+            Class->spcur = NewCursor;
+
+            /* Update the clones */
+            Class = Class->pclsClone;
+            while (Class != NULL)
+            {
+                if (Class->spcur)
+                    UserDereferenceObject(Class->spcur);
+                if (NewCursor)
+                    UserReferenceObject(NewCursor);
+                Class->spcur = NewCursor;
+                Class = Class->pclsNext;
+            }
+
+            break;
+        }
+#else
         case GCLP_HCURSOR:
             /* FIXME: Get handle from pointer to CURSOR object */
             Ret = (ULONG_PTR)Class->hCursor;
@@ -1851,6 +1916,7 @@ UserSetClassLongPtr(IN PCLS Class,
                 Class = Class->pclsNext;
             }
             break;
+#endif
 
         // MSDN:
         // hIconSm, A handle to a small icon that is associated with the window class.
@@ -1858,6 +1924,88 @@ UserSetClassLongPtr(IN PCLS Class,
         // the hIcon member for an icon of the appropriate size to use as the small icon.
         //       
         case GCLP_HICON:
+#ifdef NEW_CURSORICON
+        {
+            PCURICON_OBJECT NewIcon = NULL;
+            PCURICON_OBJECT NewSmallIcon = NULL;
+
+            if (NewLong)
+            {
+                NewIcon = UserGetCurIconObject((HCURSOR)NewLong);
+                if (!NewIcon)
+                {
+                    EngSetLastError(ERROR_INVALID_ICON_HANDLE);
+                    return 0;
+                }
+            }
+
+            if (Class->spicn)
+            {
+                Ret = (ULONG_PTR)UserHMGetHandle(Class->spicn);
+                UserDereferenceObject(Class->spicn);
+            }
+            else
+            {
+                Ret = 0;
+            }
+
+            if (Ret == NewLong)
+            {
+                /* It's a nop */
+                return Ret;
+            }
+
+            if (Ret && (Class->CSF_flags & CSF_CACHEDSMICON))
+            {
+                /* We will change the small icon */
+                UserDereferenceObject(Class->spicnSm);
+                Class->spicnSm = NULL;
+                Class->CSF_flags &= ~CSF_CACHEDSMICON;
+            }
+
+            if (NewLong && !Class->spicnSm)
+            {
+                /* Create the new small icon from the new large(?) one */
+                HICON SmallIconHandle = co_IntCopyImage(
+                    (HICON)NewLong,
+                    IMAGE_ICON,
+                    UserGetSystemMetrics( SM_CXSMICON ),
+                    UserGetSystemMetrics( SM_CYSMICON ),
+                    0);
+                if (SmallIconHandle)
+                {
+                    /* So use it */
+                    NewSmallIcon = Class->spicnSm = UserGetCurIconObject(SmallIconHandle);
+                    /* Let the handle go, we have the reference on the object */
+                    NtUserDestroyCursor(SmallIconHandle, FALSE);
+                    Class->CSF_flags |= CSF_CACHEDSMICON;
+                }
+            }
+
+            Class->spicn = NewIcon;
+
+            /* Update the clones */
+            Class = Class->pclsClone;
+            while (Class != NULL)
+            {
+                if (Class->spicn)
+                    UserDereferenceObject(Class->spicn);
+                if (NewIcon)
+                    UserReferenceObject(NewIcon);
+                Class->spicn = NewIcon;
+                if (NewSmallIcon)
+                {
+                    if (Class->spicnSm)
+                        UserDereferenceObject(Class->spicnSm);
+                    UserReferenceObject(NewSmallIcon);
+                    Class->spicnSm = NewSmallIcon;
+                    Class->CSF_flags |= CSF_CACHEDSMICON;
+                }
+                Class = Class->pclsNext;
+            }
+            break;
+        }
+#else
             /* FIXME: Get handle from pointer to ICON object */
             Ret = (ULONG_PTR)Class->hIcon;
             if (Class->hIcon == (HANDLE)NewLong) break;
@@ -1885,8 +2033,51 @@ UserSetClassLongPtr(IN PCLS Class,
                 Class = Class->pclsNext;
             }
             break;
+#endif
 
         case GCLP_HICONSM:
+#ifdef NEW_CURSORICON
+        {
+            PCURICON_OBJECT NewSmallIcon = NULL;
+
+            if (NewLong)
+            {
+                NewSmallIcon = UserGetCurIconObject((HCURSOR)NewLong);
+                if (!NewSmallIcon)
+                {
+                    EngSetLastError(ERROR_INVALID_ICON_HANDLE);
+                    return 0;
+                }
+            }
+
+            if (Class->spicnSm)
+            {
+                Ret = (ULONG_PTR)UserHMGetHandle(Class->spicnSm);
+                UserDereferenceObject(Class->spicnSm);
+            }
+            else
+            {
+                Ret = 0;
+            }
+
+            Class->CSF_flags &= ~CSF_CACHEDSMICON;
+            Class->spicnSm = NewSmallIcon;
+
+            /* Update the clones */
+            Class = Class->pclsClone;
+            while (Class != NULL)
+            {
+                if (Class->spicnSm)
+                    UserDereferenceObject(Class->spicnSm);
+                if (NewSmallIcon)
+                    UserReferenceObject(NewSmallIcon);
+                Class->CSF_flags &= ~CSF_CACHEDSMICON;
+                Class->spicnSm = NewSmallIcon;
+                Class = Class->pclsNext;
+            }
+        }
+        break;
+#else
             /* FIXME: Get handle from pointer to ICON object */
             Ret = (ULONG_PTR)Class->hIconSm;
             if (Class->hIconSm == (HANDLE)NewLong) break;
@@ -1920,6 +2111,7 @@ UserSetClassLongPtr(IN PCLS Class,
                 Class = Class->pclsNext;
             }
             break;
+#endif
 
         case GCLP_HMODULE:
             Ret = (ULONG_PTR)Class->hModule;
@@ -2011,8 +2203,16 @@ UserGetClassInfo(IN PCLS Class,
 
     lpwcx->cbClsExtra = Class->cbclsExtra;
     lpwcx->cbWndExtra = Class->cbwndExtra;
+#ifdef NEW_CURSORICON
+    lpwcx->hIcon = Class->spicn ? UserHMGetHandle(Class->spicn) : NULL;
+    lpwcx->hCursor = Class->spcur ? UserHMGetHandle(Class->spcur) : NULL;
+    lpwcx->hIconSm = Class->spicnSm ? UserHMGetHandle(Class->spicnSm) : NULL;
+#else
     lpwcx->hIcon = Class->hIcon;        /* FIXME: Get handle from pointer */
     lpwcx->hCursor = Class->hCursor;    /* FIXME: Get handle from pointer */
+    /* FIXME: Get handle from pointer */
+    lpwcx->hIconSm = Class->hIconSm ? Class->hIconSm : Class->hIconSmIntern;
+#endif
     lpwcx->hbrBackground = Class->hbrBackground;
 
     /* Copy non-string to user first. */
@@ -2042,9 +2242,6 @@ UserGetClassInfo(IN PCLS Class,
     /* FIXME: Return the string? Okay! This is performed in User32! */
     //lpwcx->lpszClassName = (LPCWSTR)((ULONG_PTR)Class->atomClassName);
 
-    /* FIXME: Get handle from pointer */
-    lpwcx->hIconSm = Class->hIconSm ? Class->hIconSm : Class->hIconSmIntern;
-
     return TRUE;
 }
 
index c8f89cf..4da91bb 100644 (file)
@@ -144,12 +144,16 @@ static BOOLEAN FASTCALL
 ReferenceCurIconByProcess(PCURICON_OBJECT CurIcon)
 {
     PPROCESSINFO Win32Process;
+    PLIST_ENTRY ListEntry;
     PCURICON_PROCESS Current;
 
     Win32Process = PsGetCurrentProcessWin32Process();
 
-    LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
+    ListEntry = CurIcon->ProcessList.Flink;
+    while (ListEntry != &CurIcon->ProcessList)
     {
+        Current = CONTAINING_RECORD(ListEntry, CURICON_PROCESS, ListEntry);
+        ListEntry = ListEntry->Flink;
         if (Current->Process == Win32Process)
         {
             /* Already registered for this process */
@@ -165,6 +169,7 @@ ReferenceCurIconByProcess(PCURICON_OBJECT CurIcon)
     }
     InsertHeadList(&CurIcon->ProcessList, &Current->ListEntry);
     Current->Process = Win32Process;
+    IntReferenceProcessInfo(Win32Process);
 
     return TRUE;
 }
@@ -173,10 +178,14 @@ PCURICON_OBJECT FASTCALL
 IntFindExistingCurIconObject(HMODULE hModule,
                              HRSRC hRsrc, LONG cx, LONG cy)
 {
+    PLIST_ENTRY ListEntry;
     PCURICON_OBJECT CurIcon;
 
-    LIST_FOR_EACH(CurIcon, &gCurIconList, CURICON_OBJECT, ListEntry)
+    ListEntry = gCurIconList.Flink;
+    while (ListEntry != &gCurIconList)
     {
+        CurIcon = CONTAINING_RECORD(ListEntry, CURICON_OBJECT, ListEntry);
+        ListEntry = ListEntry->Flink;
 
         // if (NT_SUCCESS(UserReferenceObjectByPointer(Object, TYPE_CURSOR))) // <- huh????
 //      UserReferenceObject(  CurIcon);
@@ -247,7 +256,8 @@ IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi)
     PSYSTEM_CURSORINFO CurInfo;
     HBITMAP bmpMask, bmpColor;
     BOOLEAN Ret, bListEmpty, bFound = FALSE;
-    PCURICON_PROCESS Current = NULL;
+    PLIST_ENTRY ListEntry;
+    PCURICON_PROCESS Current;
 
     /* For handles created without any data (error handling) */
     if(IsListEmpty(&CurIcon->ProcessList))
@@ -255,12 +265,16 @@ IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi)
 
     /* Now find this process in the list of processes referencing this object and
        remove it from that list */
-    LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
+    ListEntry = CurIcon->ProcessList.Flink;
+    while (ListEntry != &CurIcon->ProcessList)
     {
+        Current = CONTAINING_RECORD(ListEntry, CURICON_PROCESS, ListEntry);
+        ListEntry = ListEntry->Flink;
         if (Current->Process == ppi)
         {
             bFound = TRUE;
             bListEmpty = RemoveEntryList(&Current->ListEntry);
+            IntDereferenceProcessInfo(ppi);
             break;
         }
     }
index c6b998a..16a4661 100644 (file)
@@ -41,6 +41,14 @@ typedef struct tagACON
 
 C_ASSERT(FIELD_OFFSET(ACON, cpcur) == FIELD_OFFSET(CURICON_OBJECT, xHotspot));
 
+BOOLEAN
+IntDestroyCurIconObject(PVOID Object);
+
+VOID FASTCALL
+IntCleanupCurIconCache(PPROCESSINFO Win32Process);
+
+void FreeCurIconObject(PVOID Object);
+
 #else
 
 typedef struct tagCURICON_PROCESS
@@ -62,6 +70,9 @@ typedef struct _CURICON_OBJECT
   BYTE Shadow;
   ICONINFO IconInfo;
 } CURICON_OBJECT, *PCURICON_OBJECT;
+BOOLEAN FASTCALL IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi);
+BOOL FASTCALL IntDestroyCursor(HANDLE hCurIcon, BOOL bForce);
+HCURSOR FASTCALL IntSetCursor(HCURSOR hCursor);
 #endif
 
 typedef struct _CURSORACCELERATION_INFO
@@ -112,9 +123,6 @@ PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon);
 BOOL UserSetCursorPos( INT x, INT y, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook);
 BOOL APIENTRY UserClipCursor(RECTL *prcl);
 PSYSTEM_CURSORINFO IntGetSysCursorInfo(VOID);
-HCURSOR FASTCALL IntSetCursor(HCURSOR hCursor);
-BOOL FASTCALL IntDestroyCursor(HANDLE hCurIcon, BOOL bForce);
-BOOLEAN FASTCALL IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi);
 
 #define IntReleaseCurIconObject(CurIconObj) \
   UserDereferenceObject(CurIconObj)
index 40e2845..4360217 100644 (file)
@@ -133,7 +133,7 @@ IntCreateCurIconHandle(BOOLEAN Animated)
     CurIcon = UserCreateObject(
         gHandleTable,
         NULL,
-        NULL,
+        GetW32ThreadInfo(),
         &hCurIcon,
         TYPE_CURSOR,
         Animated ? sizeof(ACON) : sizeof(CURICON_OBJECT));
@@ -149,35 +149,23 @@ IntCreateCurIconHandle(BOOLEAN Animated)
     return hCurIcon;
 }
 
-BOOLEAN FASTCALL
-IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, BOOLEAN bForce)
+BOOLEAN
+IntDestroyCurIconObject(
+    _In_ PVOID Object)
 {
-    if(CurIcon->CURSORF_flags & CURSORF_CURRENT)
-    {
-        /* Mark the object as destroyed, and fail, as per tests */
-        TRACE("Cursor is current, marking as destroyed.\n");
-        UserDeleteObject(CurIcon->head.h, TYPE_CURSOR);
-        return FALSE;
-    }
+    PCURICON_OBJECT CurIcon = Object;
 
-    if(CurIcon->head.ppi != PsGetCurrentProcessWin32Process())
-    {
-        /* This object doesn't belong to the current process */
-        WARN("Trying to delete foreign cursor!\n");
-        UserDereferenceObject(CurIcon);
-        EngSetLastError(ERROR_DESTROY_OBJECT_OF_OTHER_THREAD);
-        return FALSE;
-    }
-    
-    /* Do not destroy it if it is shared. (And we're not forced to) */
-    if((CurIcon->CURSORF_flags & CURSORF_LRSHARED) && !bForce)
-    {
-        /* Tests show this is a valid call */
-        WARN("Trying to destroy shared cursor!\n");
-        UserDereferenceObject(CurIcon);
-        return TRUE;
-    }
+    /* We just mark the handle as being destroyed.
+     * Deleting all the stuff will be deferred to the actual struct free. */
+    return UserDeleteObject(CurIcon->head.h, TYPE_CURSOR);
+}
 
+void
+FreeCurIconObject(
+    _In_ PVOID Object)
+{
+    PCURICON_OBJECT CurIcon = Object;
+    
     if(!(CurIcon->CURSORF_flags & CURSORF_ACON))
     {
         HBITMAP bmpMask = CurIcon->hbmMask;
@@ -210,101 +198,56 @@ IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, BOOLEAN bForce)
         UINT i;
 
         for(i = 0; i < AniCurIcon->cpcur; i++)
-            IntDestroyCurIconObject(AniCurIcon->aspcur[i], TRUE);
+            IntDestroyCurIconObject(AniCurIcon->aspcur[i]);
         ExFreePoolWithTag(AniCurIcon->aspcur, USERTAG_CURSOR);
     }
 
     if (CurIcon->CURSORF_flags & CURSORF_LRSHARED)
     {
+        PPROCESSINFO ppi;
+
         if (!IS_INTRESOURCE(CurIcon->strName.Buffer))
             ExFreePoolWithTag(CurIcon->strName.Buffer, TAG_STRING);
         if (CurIcon->atomModName)
             RtlDeleteAtomFromAtomTable(gAtomTable, CurIcon->atomModName);
         CurIcon->strName.Buffer = NULL;
         CurIcon->atomModName = 0;
+
+        /* Try finding it in its process cache */
+        ppi = CurIcon->head.ppi;
+        if (ppi->pCursorCache == CurIcon)
+            ppi->pCursorCache = CurIcon->pcurNext;
+        else
+        {
+            PCURICON_OBJECT CacheCurIcon= ppi->pCursorCache;
+            while (CacheCurIcon)
+            {
+                if (CacheCurIcon->pcurNext == CurIcon)
+                {
+                    CacheCurIcon->pcurNext = CurIcon->pcurNext;
+                    break;
+                }
+                CacheCurIcon = CacheCurIcon->pcurNext;
+            }
+        }
     }
 
-    /* We were given a pointer, no need to keep the reference any longer! */
-    UserDereferenceObject(CurIcon);
-    return UserDeleteObject(CurIcon->head.h, TYPE_CURSOR);
+    /* Finally free the thing */
+    FreeProcMarkObject(CurIcon);
 }
 
 VOID FASTCALL
-IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process)
+IntCleanupCurIconCache(PPROCESSINFO Win32Process)
 {
     PCURICON_OBJECT CurIcon;
 
     /* Run through the list of icon objects */
-    while(Win32Process->pCursorCache)
+    while (Win32Process->pCursorCache)
     {
         CurIcon = Win32Process->pCursorCache;
         Win32Process->pCursorCache = CurIcon->pcurNext;
-        /* One ref for the handle, one for the list,
-         * and potentially one from an other process via SetCursor */
-        ASSERT(CurIcon->head.cLockObj <= 3);
-        IntDestroyCurIconObject(CurIcon, TRUE);
-    }
-}
-
-HCURSOR FASTCALL
-IntSetCursor(
-    HCURSOR hCursor)
-{
-    PCURICON_OBJECT pcurOld, pcurNew;
-    HCURSOR hOldCursor = NULL;
-
-    if (hCursor)
-    {
-        pcurNew = UserGetCurIconObject(hCursor);
-        if (!pcurNew)
-        {
-            EngSetLastError(ERROR_INVALID_CURSOR_HANDLE);
-            goto leave;
-        }
-        pcurNew->CURSORF_flags |= CURSORF_CURRENT;
-    }
-    else
-    {
-        pcurNew = NULL;
-    }
-
-    pcurOld = UserSetCursor(pcurNew, FALSE);
-    if (pcurOld)
-    {
-        hOldCursor = pcurOld->head.h;
-        pcurOld->CURSORF_flags &= ~CURSORF_CURRENT;
-        if(UserObjectInDestroy(hOldCursor))
-        {
-            /* Destroy it once and for all */
-            IntDestroyCurIconObject(pcurOld, TRUE);
-            hOldCursor = NULL;
-        }
-        else
-        {
-            UserDereferenceObject(pcurOld);
-        }
-    }
-leave:
-    return hOldCursor;
-}
-
-BOOL FASTCALL
-IntDestroyCursor(
-  HANDLE hCurIcon,
-  BOOL bForce)
-{
-    PCURICON_OBJECT CurIcon;
-    BOOL ret;
-
-    if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
-    {
-        return(FALSE);
+        UserDereferenceObject(CurIcon);
     }
-
-    ret = IntDestroyCurIconObject(CurIcon, bForce);
-    /* Note: IntDestroyCurIconObject will remove our reference for us! */
-
-    return ret;
 }
 
 /*
@@ -690,27 +633,56 @@ NtUserDestroyCursor(
   _In_   HANDLE hCurIcon,
   _In_   BOOL bForce)
 {
-    PCURICON_OBJECT CurIcon;
     BOOL ret;
-    DECLARE_RETURN(BOOL);
 
     TRACE("Enter NtUserDestroyCursorIcon\n");
     UserEnterExclusive();
 
-    if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
+    if (!bForce)
     {
-        RETURN(FALSE);
-    }
+        /* Maybe we have good reasons not to destroy this object */
+        PCURICON_OBJECT CurIcon = UserGetCurIconObject(hCurIcon);
+        ULONG Flags;
+        if (!CurIcon)
+        {
+            ret = FALSE;
+            goto leave;
+        }
 
-    ret = IntDestroyCurIconObject(CurIcon, bForce);
-    /* Note: IntDestroyCurIconObject will remove our reference for us! */
+        if (CurIcon->head.ppi != PsGetCurrentProcessWin32Process())
+        {
+            /* No way, you're not touching my cursor */
+            ret = FALSE;
+            UserDereferenceObject(CurIcon);
+            goto leave;
+        }
 
-    RETURN(ret);
+        Flags = CurIcon->CURSORF_flags;
+        UserDereferenceObject(CurIcon);
 
-CLEANUP:
-    TRACE("Leave NtUserDestroyCursorIcon, ret=%i\n",_ret_);
+        if (Flags & CURSORF_CURRENT)
+        {
+            WARN("Trying to delete current cursor!\n");
+            ret = FALSE;
+            goto leave;
+        }
+
+        if (Flags & CURSORF_LRSHARED)
+        {
+            WARN("Trying to delete shared cursor.\n");
+            /* This one is not an error */
+            ret = TRUE;
+            goto leave;
+        }
+    }
+
+    /* Destroy the handle */
+    ret = UserDeleteObject(hCurIcon, TYPE_CURSOR);
+
+leave:
+    TRACE("Leave NtUserDestroyCursorIcon, ret=%i\n", ret);
     UserLeave();
-    END_CLEANUP;
+    return ret;
 }
 
 
@@ -891,18 +863,8 @@ NtUserSetCursor(
     pcurOld = UserSetCursor(pcurNew, FALSE);
     if (pcurOld)
     {
-        hOldCursor = pcurOld->head.h;
         pcurOld->CURSORF_flags &= ~CURSORF_CURRENT;
-        if(UserObjectInDestroy(hOldCursor))
-        {
-            /* Destroy it once and for all */
-            IntDestroyCurIconObject(pcurOld, TRUE);
-            hOldCursor = NULL;
-        }
-        else
-        {
-            UserDereferenceObject(pcurOld);
-        }
+        UserDereferenceObject(pcurOld);
     }
 
 leave:
@@ -1088,7 +1050,7 @@ done:
         for(i = 0; i < numFrames; i++)
         {
             if(AniCurIcon->aspcur[i])
-                IntDestroyCurIconObject(AniCurIcon->aspcur[i], TRUE);
+                IntDestroyCurIconObject(AniCurIcon->aspcur[i]);
         }
         AniCurIcon->cicur = 0;
         AniCurIcon->cpcur = 0;
index 5c7e932..882385c 100644 (file)
@@ -44,7 +44,7 @@ typedef struct tagDCE
 INIT_FUNCTION NTSTATUS NTAPI InitDCEImpl(VOID);
 PDCE FASTCALL DceAllocDCE(PWND Window, DCE_TYPE Type);
 HWND FASTCALL IntWindowFromDC(HDC hDc);
-PDCE FASTCALL DceFreeDCE(PDCE dce, BOOLEAN Force);
+void FASTCALL DceFreeDCE(PDCE dce, BOOLEAN Force);
 void FASTCALL DceEmptyCache(void);
 VOID FASTCALL DceResetActiveDCEs(PWND Window);
 void FASTCALL DceFreeClassDCE(HDC);
index b4c00df..1fbd21a 100644 (file)
@@ -387,7 +387,11 @@ DefWndDoSizeMove(PWND pwnd, WORD wParam)
    RECT sizingRect, mouseRect, origRect, unmodRect;
    HDC hdc;
    LONG hittest = (LONG)(wParam & 0x0f);
+#ifdef NEW_CURSORICON
+   PCURICON_OBJECT DragCursor = NULL, OldCursor = NULL;
+#else
    HCURSOR hDragCursor = 0, hOldCursor = 0;
+#endif
    POINT minTrack, maxTrack;
    POINT capturePoint, pt;
    ULONG Style, ExStyle;
@@ -495,13 +499,35 @@ DefWndDoSizeMove(PWND pwnd, WORD wParam)
    }
 
    hdc = UserGetDCEx( pWndParent, 0, DCX_CACHE );
-
+#ifdef NEW_CURSORICON
+   if (iconic)
+   {
+       DragCursor = pwnd->pcls->spicn;
+       if (DragCursor)
+       {
+           UserReferenceObject(DragCursor);
+       }
+       else
+       {
+           HCURSOR CursorHandle = (HCURSOR)co_IntSendMessage( UserHMGetHandle(pwnd), WM_QUERYDRAGICON, 0, 0 );
+           if (CursorHandle)
+           {
+               DragCursor = UserGetCurIconObject(CursorHandle);
+           }
+           else
+           {
+               iconic = FALSE;
+           }
+       }
+   }
+#else
    if ( iconic ) /* create a cursor for dragging */
    {
-      hDragCursor = pwnd->pcls->hIcon;;
+      hDragCursor = pwnd->pcls->hIcon;
       if ( !hDragCursor ) hDragCursor = (HCURSOR)co_IntSendMessage( UserHMGetHandle(pwnd), WM_QUERYDRAGICON, 0, 0 );
       if ( !hDragCursor ) iconic = FALSE;
    }
+#endif
 
    /* repaint the window before moving it around */
    co_UserRedrawWindow( pwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN);
@@ -558,14 +584,17 @@ DefWndDoSizeMove(PWND pwnd, WORD wParam)
          if ( !moved )
          {
              moved = TRUE;
-
-              if ( iconic ) /* ok, no system popup tracking */
-              {
-                 hOldCursor = IntSetCursor(hDragCursor);
-                 UserShowCursor( TRUE );
-              }
-              else if(!DragFullWindows)
-                 UserDrawMovingFrame( hdc, &sizingRect, thickframe );
+          if ( iconic ) /* ok, no system popup tracking */
+          {
+#ifdef NEW_CURSORICON
+              OldCursor = UserSetCursor(DragCursor, FALSE);
+#else
+              hOldCursor = IntSetCursor(hDragCursor);
+#endif
+              UserShowCursor( TRUE );
+          }
+          else if(!DragFullWindows)
+             UserDrawMovingFrame( hdc, &sizingRect, thickframe );
          }
 
          if (msg.message == WM_KEYDOWN) UserSetCursorPos(pt.x, pt.y, 0, 0, FALSE);
@@ -644,10 +673,22 @@ DefWndDoSizeMove(PWND pwnd, WORD wParam)
    {
       if ( moved ) /* restore cursors, show icon title later on */
       {
-         UserShowCursor( FALSE );
-         IntSetCursor( hOldCursor );
+          UserShowCursor( FALSE );
+#ifdef NEW_CURSORICON
+          OldCursor = UserSetCursor(OldCursor, FALSE);
+#else
+          IntSetCursor( hOldCursor );
+#endif
       }
+#ifdef NEW_CURSORICON
+      /* It could be that the cursor was already changed while we were proceeding,
+       * so we must unreference whatever cursor was current at the time we restored the old one.
+       * Maybe it is DragCursor, but maybe it is another one and DragCursor got already freed.
+       */
+      UserDereferenceObject(OldCursor);
+#else
       IntDestroyCursor( hDragCursor, FALSE );
+#endif
    }
    else if ( moved && !DragFullWindows )
       UserDrawMovingFrame( hdc, &sizingRect, thickframe );
@@ -990,6 +1031,19 @@ IntDefWindowProc(
          hDC = IntBeginPaint(Wnd, &Ps);
          if (hDC)
          {
+#ifdef NEW_CURSORICON
+             if (((Wnd->style & WS_MINIMIZE) != 0) && (Wnd->pcls->spicn))
+             {
+                 RECT ClientRect;
+                 INT x, y;
+
+                 ERR("Doing Paint and Client area is empty!\n");
+                 IntGetClientRect(Wnd, &ClientRect);
+                 x = (ClientRect.right - ClientRect.left - UserGetSystemMetrics(SM_CXICON)) / 2;
+                 y = (ClientRect.bottom - ClientRect.top - UserGetSystemMetrics(SM_CYICON)) / 2;
+                 UserDrawIconEx(hDC, x, y, Wnd->pcls->spicn, 0, 0, 0, 0, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE);
+             }
+#else
              HICON hIcon;
              if (((Wnd->style & WS_MINIMIZE) != 0) && (hIcon = Wnd->pcls->hIcon))
              {
@@ -1002,7 +1056,9 @@ IntDefWindowProc(
                  x = (ClientRect.right - ClientRect.left - UserGetSystemMetrics(SM_CXICON)) / 2;
                  y = (ClientRect.bottom - ClientRect.top - UserGetSystemMetrics(SM_CYICON)) / 2;
                  UserDrawIconEx( hDC, x, y, pIcon, 0, 0, 0, 0, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE );
+                 UserDereferenceObject(pIcon);
              }
+#endif
              IntEndPaint(Wnd, &Ps);
          }
          return (0);
@@ -1096,23 +1152,43 @@ IntDefWindowProc(
    return lResult;
 }
 
-HICON FASTCALL NC_IconForWindow( PWND pWnd )
+PCURICON_OBJECT FASTCALL NC_IconForWindow( PWND pWnd )
 {
-   HICON hIcon = 0;
+    PCURICON_OBJECT pIcon = NULL;
+    HICON hIcon;
    // First thing to do, init the Window Logo icons.
    if (!gpsi->hIconSmWindows) co_IntSetWndIcons();
 
-   if (!hIcon) hIcon = UserGetProp(pWnd, gpsi->atomIconSmProp);
+   //FIXME: Some callers use this function as if it returns a boolean saying "this window has an icon".
+   //FIXME: Hence we must return a pointer with no reference count.
+   //FIXME: This is bad and we should feel bad.
+
+   hIcon = UserGetProp(pWnd, gpsi->atomIconSmProp);
    if (!hIcon) hIcon = UserGetProp(pWnd, gpsi->atomIconProp);
+#ifdef NEW_CURSORICON
+   if (!hIcon && pWnd->pcls->spicnSm)
+       return pWnd->pcls->spicnSm;
+   if (!hIcon && pWnd->pcls->spicn)
+       return pWnd->pcls->spicn;
+#else
    if (!hIcon) hIcon = pWnd->pcls->hIconSm;
    if (!hIcon) hIcon = pWnd->pcls->hIcon;
+#endif
 
-   if (!hIcon && pWnd->style & DS_MODALFRAME)
+   if (!hIcon && (pWnd->style & DS_MODALFRAME))
    {
       if (!hIcon) hIcon = gpsi->hIconSmWindows; // Both are IDI_WINLOGO Small
       if (!hIcon) hIcon = gpsi->hIconWindows;   // Reg size.
    }
-   return hIcon;
+   if (hIcon)
+   {
+       pIcon = UserGetCurIconObject(hIcon);
+       if (pIcon)
+       {
+           UserDereferenceObject(pIcon);
+       }
+   }
+   return pIcon;
 }
 
 DWORD FASTCALL
index 69ab304..2f7838b 100644 (file)
@@ -662,9 +662,15 @@ DesktopWindowProc(PWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *lRe
           {
               return TRUE;
           }
+#ifdef NEW_CURSORICON
+          pcurNew->CURSORF_flags |= CURSORF_CURRENT;
+#endif
           pcurOld = UserSetCursor(pcurNew, FALSE);
           if (pcurOld)
           {
+#ifdef NEW_CURSORICON
+               pcurOld->CURSORF_flags &= ~CURSORF_CURRENT;
+#endif
                UserDereferenceObject(pcurOld);
           }
           return TRUE;
@@ -806,12 +812,17 @@ HWND* FASTCALL
 UserBuildShellHookHwndList(PDESKTOP Desktop)
 {
    ULONG entries=0;
+   PLIST_ENTRY ListEntry;
    PSHELL_HOOK_WINDOW Current;
    HWND* list;
 
    /* FIXME: If we save nb elements in desktop, we dont have to loop to find nb entries */
-   LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
+   ListEntry = Desktop->ShellHookWindows.Flink;
+   while (ListEntry != &Desktop->ShellHookWindows)
+   {
+      ListEntry = ListEntry->Flink;
       entries++;
+   }
 
    if (!entries) return NULL;
 
@@ -820,8 +831,13 @@ UserBuildShellHookHwndList(PDESKTOP Desktop)
    {
       HWND* cursor = list;
 
-      LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
+      ListEntry = Desktop->ShellHookWindows.Flink;
+      while (ListEntry != &Desktop->ShellHookWindows)
+      {
+         Current = CONTAINING_RECORD(ListEntry, SHELL_HOOK_WINDOW, ListEntry);
+         ListEntry = ListEntry->Flink;
          *cursor++ = Current->hWnd;
+      }
 
       *cursor = NULL; /* Nullterm list */
    }
@@ -930,10 +946,14 @@ BOOL IntDeRegisterShellHookWindow(HWND hWnd)
 {
    PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
    PDESKTOP Desktop = pti->rpdesk;
+   PLIST_ENTRY ListEntry;
    PSHELL_HOOK_WINDOW Current;
 
-   LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
+   ListEntry = Desktop->ShellHookWindows.Flink;
+   while (ListEntry != &Desktop->ShellHookWindows)
    {
+      Current = CONTAINING_RECORD(ListEntry, SHELL_HOOK_WINDOW, ListEntry);
+      ListEntry = ListEntry->Flink;
       if (Current->hWnd == hWnd)
       {
          RemoveEntryList(&Current->ListEntry);
index f6f1c3d..4705199 100644 (file)
@@ -761,7 +761,8 @@ UserChangeDisplaySettings(
         ulResult = PDEVOBJ_bSwitchMode(ppdev, pdm);
 
         /* Restore mouse pointer, no hooks called */
-        UserSetCursor(pvOldCursor, TRUE);
+        pvOldCursor = UserSetCursor(pvOldCursor, TRUE);
+        ASSERT(pvOldCursor == NULL);
 
         /* Check for failure */
         if (!ulResult)
index c668bbb..bfc68de 100644 (file)
@@ -238,6 +238,11 @@ DestroyProcessInfo(PEPROCESS Process)
         ppiCurrent->hdeskStartup = NULL;
     }
 
+#ifdef NEW_CURSORICON
+    /* Clean up the process icon cache */
+    IntCleanupCurIconCache(ppiCurrent);
+#endif
+
     /* The process is dying */
     PsSetProcessWin32Process(Process, NULL, ppiCurrent);
     ppiCurrent->peProcess = NULL;
index 4dbe59f..8d6a76c 100644 (file)
@@ -2882,6 +2882,13 @@ NtUserWaitForInputIdle( IN HANDLE hProcess,
 
     TRACE("WFII: ppi %p\n", W32Process);
     TRACE("WFII: waiting for %p\n", Handles[1] );
+
+    /*
+     * We must add a refcount to our current PROCESSINFO,
+     * because anything could happen (including process death) we're leaving win32k
+     */
+    IntReferenceProcessInfo(W32Process);
+
     do
     {
         UserLeave();
@@ -2935,6 +2942,7 @@ WaitExit:
        pti->pClientInfo->dwTIFlags = pti->TIF_flags;
     }
     W32Process->W32PF_flags &= ~W32PF_WAITFORINPUTIDLE;
+    IntDereferenceProcessInfo(W32Process);
     ObDereferenceObject(Process);
     UserLeave();
     return Status;
index 94b2b39..3a7f3b3 100644 (file)
@@ -146,14 +146,20 @@ UserSetCursor(
         {
             /* Call GDI to set the new screen cursor */
 #ifdef NEW_CURSORICON
+            PCURICON_OBJECT CursorFrame = NewCursor;
+            if(NewCursor->CURSORF_flags & CURSORF_ACON)
+            {
+                FIXME("Should animate the cursor, using only the first frame now.\n");
+                CursorFrame = ((PACON)NewCursor)->aspcur[0];
+            }
             GreSetPointerShape(hdcScreen,
-                               NewCursor->hbmAlpha ? NULL : NewCursor->hbmMask,
-                               NewCursor->hbmAlpha ? NewCursor->hbmAlpha : NewCursor->hbmColor,
-                               NewCursor->xHotspot,
-                               NewCursor->yHotspot,
+                               CursorFrame->hbmAlpha ? NULL : NewCursor->hbmMask,
+                               CursorFrame->hbmAlpha ? NewCursor->hbmAlpha : NewCursor->hbmColor,
+                               CursorFrame->xHotspot,
+                               CursorFrame->yHotspot,
                                gpsi->ptCursor.x,
                                gpsi->ptCursor.y,
-                               NewCursor->hbmAlpha ? SPS_ALPHA : 0);
+                               CursorFrame->hbmAlpha ? SPS_ALPHA : 0);
 #else
             GreSetPointerShape(hdcScreen,
                                NewCursor->IconInfo.hbmMask,
index 01964de..3963314 100644 (file)
@@ -168,7 +168,7 @@ static PVOID AllocProcMarkObject(
     return ObjHead;
 }
 
-static void FreeProcMarkObject(
+void FreeProcMarkObject(
     _In_ PVOID Object)
 {
     PPROCESSINFO ppi = ((PPROCMARKHEAD)Object)->ppi;
@@ -218,7 +218,11 @@ static const struct
     { NULL,                     NULL,                       NULL },                 /* TYPE_FREE */
     { AllocDeskThreadObject,    co_UserDestroyWindow,       FreeDeskThreadObject }, /* TYPE_WINDOW */
     { AllocDeskProcObject,      UserDestroyMenuObject,      FreeDeskProcObject },   /* TYPE_MENU */
+#ifndef NEW_CURSORICON
     { AllocProcMarkObject,      /*UserCursorCleanup*/NULL,  FreeProcMarkObject },   /* TYPE_CURSOR */
+#else
+    { AllocProcMarkObject,      IntDestroyCurIconObject,    FreeCurIconObject },    /* TYPE_CURSOR */
+#endif
     { AllocSysObject,           /*UserSetWindowPosCleanup*/NULL, FreeSysObject },   /* TYPE_SETWINDOWPOS */
     { AllocDeskThreadObject,    IntRemoveHook,              FreeDeskThreadObject }, /* TYPE_HOOK */
     { AllocSysObject,           /*UserClipDataCleanup*/NULL,FreeSysObject },        /* TYPE_CLIPDATA */
@@ -686,6 +690,7 @@ UserReferenceObjectByHandle(HANDLE handle, HANDLE_TYPE type)
     return object;
 }
 
+#ifndef NEW_CURSORICON
 VOID
 FASTCALL
 UserSetObjectOwner(PVOID obj, HANDLE_TYPE type, PVOID owner)
@@ -710,15 +715,17 @@ UserSetObjectOwner(PVOID obj, HANDLE_TYPE type, PVOID owner)
             return;
     }
 
-    oldppi->UserHandleCount--;
-    IntDereferenceProcessInfo(oldppi);
-    ppi->UserHandleCount++;
-    IntReferenceProcessInfo(ppi);
 #if DBG
     oldppi->DbgHandleCount[type]--;
     ppi->DbgHandleCount[type]++;
 #endif
+
+    oldppi->UserHandleCount--;
+    IntDereferenceProcessInfo(oldppi);
+    ppi->UserHandleCount++;
+    IntReferenceProcessInfo(ppi);
 }
+#endif
 
 BOOLEAN
 UserDestroyObjectsForOwner(PUSER_HANDLE_TABLE Table, PVOID Owner)
@@ -739,6 +746,7 @@ UserDestroyObjectsForOwner(PUSER_HANDLE_TABLE Table, PVOID Owner)
         if (Entry->flags & HANDLEENTRY_INDESTROY)
             continue;
 
+#ifndef NEW_CURSORICON
         /* Spcial case for cursors until cursoricon_new is there */
         if (Entry->type == TYPE_CURSOR)
         {
@@ -749,6 +757,7 @@ UserDestroyObjectsForOwner(PUSER_HANDLE_TABLE Table, PVOID Owner)
             }
             continue;
         }
+#endif
 
         /* Call destructor */
         if (!ObjectCallbacks[Entry->type].ObjectDestroy(Entry->ptr))
index e90d66c..1ed672b 100644 (file)
@@ -17,7 +17,9 @@ PVOID UserGetObjectNoErr(PUSER_HANDLE_TABLE, HANDLE, HANDLE_TYPE);
 BOOL FASTCALL UserCreateHandleTable(VOID);
 BOOL FASTCALL UserObjectInDestroy(HANDLE);
 void DbgUserDumpHandleTable();
+#ifndef NEW_CURSORICON
 VOID FASTCALL UserSetObjectOwner(PVOID obj, HANDLE_TYPE type, PVOID owner);
+#endif
 PVOID FASTCALL ValidateHandle(HANDLE handle, HANDLE_TYPE type);
 BOOLEAN UserDestroyObjectsForOwner(PUSER_HANDLE_TABLE Table, PVOID Owner);
 
@@ -54,4 +56,6 @@ UserDerefObjectCo(PVOID obj)
     UserDereferenceObject(obj);
 }
 
+void FreeProcMarkObject(_In_ PVOID Object);
+
 /* EOF */
index 362bdda..c6335fb 100644 (file)
@@ -2122,13 +2122,17 @@ BOOL UserDrawCaption(
    {
       PCURICON_OBJECT pIcon = NULL;
 
-      if (!hIcon && pWnd)
+      if (hIcon)
       {
-          hIcon = NC_IconForWindow( pWnd );
+          pIcon = UserGetCurIconObject(hIcon);
+      }
+      else if (pWnd)
+      {
+          pIcon = NC_IconForWindow(pWnd);
+          // FIXME: NC_IconForWindow should reference it for us */
+          if (pIcon)
+              UserReferenceObject(pIcon);
       }
-
-      if (hIcon)
-         pIcon = UserGetCurIconObject(hIcon);
 
       if (pIcon)
       {
index 76cf6e0..da08b53 100644 (file)
@@ -10,4 +10,4 @@ BOOL FASTCALL IntValidateParent(PWND Child, PREGION ValidateRgn, BOOL Recurse);
 BOOL FASTCALL IntIsWindowDirty(PWND);
 BOOL FASTCALL IntEndPaint(PWND,PPAINTSTRUCT);
 HDC FASTCALL IntBeginPaint(PWND,PPAINTSTRUCT);
-HICON FASTCALL NC_IconForWindow( PWND );
+PCURICON_OBJECT FASTCALL NC_IconForWindow( PWND );
index b7d3fc3..e3f8d8b 100644 (file)
@@ -51,15 +51,16 @@ DCE*
 FASTCALL
 DceGetDceFromDC(HDC hdc)
 {
-    LIST_ENTRY* Entry = LEDce.Flink;
+    PLIST_ENTRY ListEntry;
     DCE* dce;
 
-    while (Entry != &LEDce)
+    ListEntry = LEDce.Flink;
+    while (ListEntry != &LEDce)
     {
-        dce = CONTAINING_RECORD(Entry, DCE, List);
+        dce = CONTAINING_RECORD(ListEntry, DCE, List);
+        ListEntry = ListEntry->Flink;
         if (dce->hDC == hdc)
             return dce;
-        Entry = Entry->Flink;
     }
 
     return NULL;
@@ -247,7 +248,7 @@ noparent:
 
       if (Dce->hrgnClip != NULL)
           RgnClip = REGION_LockRgn(Dce->hrgnClip);
-      
+
       if (RgnClip)
       {
          IntGdiCombineRgn(RgnVisible, RgnVisible, RgnClip, RGN_AND);
@@ -330,18 +331,16 @@ DceReleaseDC(DCE* dce, BOOL EndPaint)
 #if 0 // Need to research and fix before this is a "growing" issue.
       if (++DCECache > 32)
       {
-         pLE = LEDce.Flink;
-         pDCE = CONTAINING_RECORD(pLE, DCE, List);
-         do
+         ListEntry = LEDce.Flink;
+         while (ListEntry != &LEDce)
          {
+            pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
+            ListEntry = ListEntry->Flink;
             if (!(pDCE->DCXFlags & DCX_DCEBUSY))
             {  /* Free the unused cache DCEs. */
-               pDCE = DceFreeDCE(pDCE, TRUE);
-               if (!pDCE) break;
-               continue;
+               DceFreeDCE(pDCE, TRUE);
             }
          }
-         while (pLE != &LEDce );
       }
 #endif
    }
@@ -359,7 +358,7 @@ UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
    BOOL bUpdateVisRgn = TRUE;
    HDC hDC = NULL;
    PPROCESSINFO ppi;
-   PLIST_ENTRY pLE;
+   PLIST_ENTRY ListEntry;
 
    if (NULL == Wnd)
    {
@@ -404,8 +403,11 @@ UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
             Flags |= DCX_CLIPCHILDREN;
          }
          /* If minized with icon in the set, we are forced to be cheap! */
-         if (Wnd->style & WS_MINIMIZE &&
-             Wnd->pcls->hIcon)
+#ifdef NEW_CURSORICON
+         if (Wnd->style & WS_MINIMIZE && Wnd->pcls->spicn)
+#else
+         if (Wnd->style & WS_MINIMIZE && Wnd->pcls->hIcon)
+#endif
          {
             Flags |= DCX_CACHE;
          }
@@ -463,15 +465,11 @@ UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
       DCE* DceEmpty = NULL;
       DCE* DceUnused = NULL;
       KeEnterCriticalRegion();
-      pLE = LEDce.Flink;
-      Dce = CONTAINING_RECORD(pLE, DCE, List);
-      do
+      ListEntry = LEDce.Flink;
+      while (ListEntry != &LEDce)
       {
-// The reason for this you may ask?
-// Well, it seems ReactOS calls GetDC without first creating a desktop DC window!
-// Need to test for null here. Not sure if this is a bug or a feature.
-// First time use hax, need to use DceAllocDCE during window display init.
-         if (!Dce) break;
+         Dce = CONTAINING_RECORD(ListEntry, DCE, List);
+         ListEntry = ListEntry->Flink;
 //
 // The way I understand this, you can have more than one DC per window.
 // Only one Owned if one was requested and saved and one Cached.
@@ -490,10 +488,7 @@ UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
                break;
             }
          }
-         pLE = Dce->List.Flink;
-         Dce = CONTAINING_RECORD(pLE, DCE, List);
       }
-      while (pLE != &LEDce);
       KeLeaveCriticalRegion();
 
       Dce = (DceEmpty == NULL) ? DceUnused : DceEmpty;
@@ -510,20 +505,19 @@ UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
    else // If we are here, we are POWNED or having CLASS.
    {
       KeEnterCriticalRegion();
-      pLE = LEDce.Flink;
-      Dce = CONTAINING_RECORD(pLE, DCE, List);
-      do
-      {   // Check for Window handle than HDC match for CLASS.
+      ListEntry = LEDce.Flink;
+      while (ListEntry != &LEDce)
+      {
+          Dce = CONTAINING_RECORD(ListEntry, DCE, List);
+          ListEntry = ListEntry->Flink;
+          // Check for Window handle than HDC match for CLASS.
           if (Dce->hwndCurrent == Wnd->head.h)
           {
              bUpdateVisRgn = FALSE;
              break;
           }
           if (Dce->hDC == hDC) break;
-          pLE = Dce->List.Flink;
-          Dce = CONTAINING_RECORD(pLE, DCE, List);
       }
-      while (pLE != &LEDce);
       KeLeaveCriticalRegion();
 
       if ( (Flags & (DCX_INTERSECTRGN|DCX_EXCLUDERGN)) &&
@@ -554,11 +548,8 @@ UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
     *   http://www.reactos.org/archives/public/ros-dev/2008-July/010498.html
     *   http://www.reactos.org/archives/public/ros-dev/2008-July/010499.html
     */
-   if (pLE != &LEDce)
-   {
-      RemoveEntryList(&Dce->List);
-      InsertHeadList(&LEDce, &Dce->List);
-   }
+   RemoveEntryList(&Dce->List);
+   InsertHeadList(&LEDce, &Dce->List);
 
    /* Introduced in rev 6691 and modified later. */
    if ( (Flags & DCX_INTERSECTUPDATE) && !ClipRegion )
@@ -637,17 +628,13 @@ UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
 /***********************************************************************
  *           DceFreeDCE
  */
-PDCE FASTCALL
+void FASTCALL
 DceFreeDCE(PDCE pdce, BOOLEAN Force)
 {
-  DCE *ret;
-  PLIST_ENTRY pLE;
   BOOL Hit = FALSE;
 
-  if (NULL == pdce) return NULL;
-
-  pLE = pdce->List.Flink;
-  ret = CONTAINING_RECORD(pLE, DCE, List);
+  ASSERT(pdce != NULL);
+  if (NULL == pdce) return;
 
   pdce->DCXFlags |= DCX_INDESTROY;
 
@@ -683,18 +670,10 @@ DceFreeDCE(PDCE pdce, BOOLEAN Force)
 
   RemoveEntryList(&pdce->List);
 
-  if (IsListEmpty(&pdce->List))
-  {
-      ERR("List is Empty! DCE! -> %p\n" , pdce);
-      return NULL;
-  }
-
   ExFreePoolWithTag(pdce, USERTAG_DCE);
 
   DCECount--;
   TRACE("Freed DCE's! %d \n", DCECount);
-
-  return ret;
 }
 
 /***********************************************************************
@@ -706,7 +685,7 @@ void FASTCALL
 DceFreeWindowDCE(PWND Window)
 {
   PDCE pDCE;
-  PLIST_ENTRY pLE;
+  PLIST_ENTRY ListEntry;
 
   if (DCECount <= 0)
   {
@@ -714,20 +693,11 @@ DceFreeWindowDCE(PWND Window)
      return;
   }
 
-  pLE = LEDce.Flink;
-  pDCE = CONTAINING_RECORD(pLE, DCE, List);
-  do
+  ListEntry = LEDce.Flink;
+  while (ListEntry != &LEDce)
   {
-     if (!pDCE)
-     {
-        ERR("FreeWindowDCE No DCE Pointer!\n");
-        break;
-     }
-     if (IsListEmpty(&pDCE->List))
-     {
-        ERR("FreeWindowDCE List is Empty!!!!\n");
-        break;
-     }
+     pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
+     ListEntry = ListEntry->Flink;
      if ( pDCE->hwndCurrent == Window->head.h &&
           !(pDCE->DCXFlags & DCX_DCEEMPTY) )
      {
@@ -755,8 +725,7 @@ DceFreeWindowDCE(PWND Window)
            }
            else if (Window->pcls->style & CS_OWNDC) /* Owned DCE */
            {
-              pDCE = DceFreeDCE(pDCE, FALSE);
-              if (!pDCE) break;
+              DceFreeDCE(pDCE, FALSE);
               continue;
            }
            else
@@ -785,76 +754,61 @@ DceFreeWindowDCE(PWND Window)
            pDCE->pwndOrg = pDCE->pwndClip = NULL;
         }
      }
-     pLE = pDCE->List.Flink;
-     pDCE = CONTAINING_RECORD(pLE, DCE, List);
   }
-  while (pLE != &LEDce);
 }
 
 void FASTCALL
 DceFreeClassDCE(HDC hDC)
 {
    PDCE pDCE;
-   PLIST_ENTRY pLE;
-   pLE = LEDce.Flink;
-   pDCE = CONTAINING_RECORD(pLE, DCE, List);
+   PLIST_ENTRY ListEntry;
 
-   do
+   ListEntry = LEDce.Flink;
+   while (ListEntry != &LEDce)
    {
-       if(!pDCE) break;
+       pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
+       ListEntry = ListEntry->Flink;
        if (pDCE->hDC == hDC)
        {
-          pDCE = DceFreeDCE(pDCE, TRUE); // Might have gone cheap!
-          if (!pDCE) break;
-          continue;
+          DceFreeDCE(pDCE, TRUE); // Might have gone cheap!
        }
-       pLE = pDCE->List.Flink;
-       pDCE = CONTAINING_RECORD(pLE, DCE, List);
    }
-   while (pLE != &LEDce);
 }
 
 void FASTCALL
 DceFreeThreadDCE(PTHREADINFO pti)
 {
    PDCE pDCE;
-   PLIST_ENTRY pLE;
-   pLE = LEDce.Flink;
-   pDCE = CONTAINING_RECORD(pLE, DCE, List);
+   PLIST_ENTRY ListEntry;
 
-   do
+   ListEntry = LEDce.Flink;
+   while (ListEntry != &LEDce)
    {
-       if(!pDCE) break;
+       pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
+       ListEntry = ListEntry->Flink;
        if (pDCE->ptiOwner == pti)
        {
           if (pDCE->DCXFlags & DCX_CACHE)
           {
-             pDCE = DceFreeDCE(pDCE, TRUE);
-             if (!pDCE) break;
-             continue;
+             DceFreeDCE(pDCE, TRUE);
           }
        }
-       pLE = pDCE->List.Flink;
-       pDCE = CONTAINING_RECORD(pLE, DCE, List);
    }
-   while (pLE != &LEDce);
 }
 
 VOID FASTCALL
 DceEmptyCache(VOID)
 {
    PDCE pDCE;
-   PLIST_ENTRY pLE;
-   pLE = LEDce.Flink;
-   pDCE = CONTAINING_RECORD(pLE, DCE, List);
+   PLIST_ENTRY ListEntry;
 
-   do
+   ListEntry = LEDce.Flink;
+   while (ListEntry != &LEDce)
    {
-      if(!pDCE) break;
-      pDCE = DceFreeDCE(pDCE, TRUE);
-      if(!pDCE) break;
+      pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
+      ListEntry = ListEntry->Flink;
+      DceFreeDCE(pDCE, TRUE);
    }
-   while (pLE != &LEDce);
 }
 
 VOID FASTCALL
@@ -865,19 +819,18 @@ DceResetActiveDCEs(PWND Window)
    PWND CurrentWindow;
    INT DeltaX;
    INT DeltaY;
-   PLIST_ENTRY pLE;
+   PLIST_ENTRY ListEntry;
 
    if (NULL == Window)
    {
       return;
    }
-   pLE = LEDce.Flink;
-   pDCE = CONTAINING_RECORD(pLE, DCE, List);
 
-   do
+   ListEntry = LEDce.Flink;
+   while (ListEntry != &LEDce)
    {
-      if(!pDCE) break;
-      if(pLE == &LEDce) break;
+      pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
+      ListEntry = ListEntry->Flink;
       if (0 == (pDCE->DCXFlags & (DCX_DCEEMPTY|DCX_INDESTROY)))
       {
          if (Window->head.h == pDCE->hwndCurrent)
@@ -892,8 +845,6 @@ DceResetActiveDCEs(PWND Window)
                CurrentWindow = UserGetWindowObject(pDCE->hwndCurrent);
             if (NULL == CurrentWindow)
             {
-               pLE = pDCE->List.Flink;
-               pDCE = CONTAINING_RECORD(pLE, DCE, List);
                continue;
             }
          }
@@ -901,8 +852,6 @@ DceResetActiveDCEs(PWND Window)
          if (!GreIsHandleValid(pDCE->hDC) ||
              (dc = DC_LockDc(pDCE->hDC)) == NULL)
          {
-            pLE = pDCE->List.Flink;
-            pDCE = CONTAINING_RECORD(pLE, DCE, List);
             continue;
          }
          if (Window == CurrentWindow || IntIsChildWindow(Window, CurrentWindow))
@@ -937,23 +886,21 @@ DceResetActiveDCEs(PWND Window)
          DceUpdateVisRgn(pDCE, CurrentWindow, pDCE->DCXFlags);
          IntGdiSetHookFlags(pDCE->hDC, DCHF_VALIDATEVISRGN);
       }
-      pLE = pDCE->List.Flink;
-      pDCE = CONTAINING_RECORD(pLE, DCE, List);
    }
-   while (pLE != &LEDce);
 }
 
 HWND FASTCALL
 IntWindowFromDC(HDC hDc)
 {
   DCE *Dce;
-  PLIST_ENTRY pLE;
+  PLIST_ENTRY ListEntry;
   HWND Ret = NULL;
 
-  pLE = LEDce.Flink;
-  Dce = CONTAINING_RECORD(pLE, DCE, List);
-  do
+  ListEntry = LEDce.Flink;
+  while (ListEntry != &LEDce)
   {
+      Dce = CONTAINING_RECORD(ListEntry, DCE, List);
+      ListEntry = ListEntry->Flink;
       if (Dce->hDC == hDc)
       {
          if (Dce->DCXFlags & DCX_INDESTROY)
@@ -962,10 +909,7 @@ IntWindowFromDC(HDC hDc)
             Ret = Dce->hwndCurrent;
          break;
       }
-      pLE = Dce->List.Flink;
-      Dce = CONTAINING_RECORD(pLE, DCE, List);
   }
-  while (pLE != &LEDce);
   return Ret;
 }
 
@@ -973,25 +917,22 @@ INT FASTCALL
 UserReleaseDC(PWND Window, HDC hDc, BOOL EndPaint)
 {
   PDCE dce;
-  PLIST_ENTRY pLE;
+  PLIST_ENTRY ListEntry;
   INT nRet = 0;
   BOOL Hit = FALSE;
 
   TRACE("%p %p\n", Window, hDc);
-  pLE = LEDce.Flink;
-  dce = CONTAINING_RECORD(pLE, DCE, List);
-  do
+  ListEntry = LEDce.Flink;
+  while (ListEntry != &LEDce)
   {
-     if(!dce) break;
+     dce = CONTAINING_RECORD(ListEntry, DCE, List);
+     ListEntry = ListEntry->Flink;
      if (dce->hDC == hDc)
      {
         Hit = TRUE;
         break;
      }
-     pLE = dce->List.Flink;
-     dce = CONTAINING_RECORD(pLE, DCE, List);
   }
-  while (pLE != &LEDce );
 
   if ( Hit && (dce->DCXFlags & DCX_DCEBUSY))
   {
index 56763de..5c5363c 100644 (file)
@@ -1674,7 +1674,24 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
    }
 
    pWnd->head.pti->cWindows++;
-
+#ifdef NEW_CURSORICON
+   if (Class->spicn && !Class->spicnSm)
+   {
+       HICON IconSmHandle = co_IntCopyImage(
+           UserHMGetHandle(Class->spicn),
+           IMAGE_ICON,
+           UserGetSystemMetrics( SM_CXSMICON ),
+           UserGetSystemMetrics( SM_CYSMICON ),
+           0);
+       if (IconSmHandle)
+       {
+           Class->spicnSm = UserGetCurIconObject(IconSmHandle);
+           /* We can delete the handle, only the pointer is of interest */
+           NtUserDestroyCursor(IconSmHandle, FALSE);
+           Class->CSF_flags |= CSF_CACHEDSMICON;
+       }
+   }
+#else
    if (Class->hIcon && !Class->hIconSm)
    {
       Class->hIconSmIntern = co_IntCopyImage( Class->hIcon, IMAGE_ICON,
@@ -1683,6 +1700,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
       TRACE("IntCreateWindow hIconSmIntern %p\n",Class->hIconSmIntern);
       Class->CSF_flags |= CSF_CACHEDSMICON;
    }
+#endif
 
    if (pWnd->pcls->CSF_flags & CSF_SERVERSIDEPROC)
       pWnd->state |= WNDS_SERVERSIDEWINDOWPROC;
index b32c9d5..ae10e8c 100644 (file)
@@ -330,7 +330,10 @@ RealSystemParametersInfoA(UINT uiAction,
           }
 
           Ret = NtUserSystemParametersInfo(SPI_SETDESKWALLPAPER, uiParam, pvParam, fWinIni);
-          RtlFreeUnicodeString(&ustrWallpaper);
+
+          if (pvParam)
+            RtlFreeUnicodeString(&ustrWallpaper);
+
           return Ret;
       }
     }
index 7ca7493..fbfa9a6 100644 (file)
@@ -712,7 +712,19 @@ IntGetClassLongA(PWND Wnd, PCLS Class, int nIndex)
             case GCW_ATOM:
                 Ret = (ULONG_PTR)Class->atomClassName;
                 break;
+#ifdef NEW_CURSORICON
+            case GCLP_HCURSOR:
+                Ret = Class->spcur ? (ULONG_PTR)((PPROCMARKHEAD)DesktopPtrToUser(Class->spcur))->h : 0;
+                break;
+
+            case GCLP_HICON:
+                Ret = Class->spicn ? (ULONG_PTR)((PPROCMARKHEAD)DesktopPtrToUser(Class->spicn))->h : 0;
+                break;
 
+            case GCLP_HICONSM:
+                Ret = Class->spicnSm ? (ULONG_PTR)((PPROCMARKHEAD)DesktopPtrToUser(Class->spicnSm))->h : 0;
+                break;
+#else
             case GCLP_HCURSOR:
                 /* FIXME - get handle from pointer to CURSOR object */
                 Ret = (ULONG_PTR)Class->hCursor;
@@ -727,6 +739,7 @@ IntGetClassLongA(PWND Wnd, PCLS Class, int nIndex)
                 /* FIXME - get handle from pointer to ICON object */
                 Ret = (ULONG_PTR)(Class->hIconSm ? Class->hIconSm : Class->hIconSmIntern);
                 break;
+#endif
 
             case GCLP_WNDPROC:
                 Ret = IntGetClsWndProc(Wnd, Class, TRUE);
@@ -790,6 +803,19 @@ IntGetClassLongW (PWND Wnd, PCLS Class, int nIndex)
                 Ret = (ULONG_PTR)Class->atomClassName;
                 break;
 
+#ifdef NEW_CURSORICON
+            case GCLP_HCURSOR:
+                Ret = Class->spcur ? (ULONG_PTR)((PPROCMARKHEAD)DesktopPtrToUser(Class->spcur))->h : 0;
+                break;
+
+            case GCLP_HICON:
+                Ret = Class->spicn ? (ULONG_PTR)((PPROCMARKHEAD)DesktopPtrToUser(Class->spicn))->h : 0;
+                break;
+
+            case GCLP_HICONSM:
+                Ret = Class->spicnSm ? (ULONG_PTR)((PPROCMARKHEAD)DesktopPtrToUser(Class->spicnSm))->h : 0;
+                break;
+#else
             case GCLP_HCURSOR:
                 /* FIXME - get handle from pointer to CURSOR object */
                 Ret = (ULONG_PTR)Class->hCursor;
@@ -804,6 +830,7 @@ IntGetClassLongW (PWND Wnd, PCLS Class, int nIndex)
                 /* FIXME - get handle from pointer to ICON object */
                 Ret = (ULONG_PTR)(Class->hIconSm ? Class->hIconSm : Class->hIconSmIntern);
                 break;
+#endif
 
             case GCLP_WNDPROC:
                 Ret = IntGetClsWndProc(Wnd, Class, FALSE);
index 5b90e29..ee3cd80 100644 (file)
@@ -622,10 +622,7 @@ User32DefWindowProc(HWND hWnd,
         case WM_RBUTTONUP:
         {
             POINT Pt;
-            if (hWnd == GetCapture())
-            {
-                ReleaseCapture();
-            }
+
             Pt.x = GET_X_LPARAM(lParam);
             Pt.y = GET_Y_LPARAM(lParam);
             ClientToScreen(hWnd, &Pt);