cmake_policy(SET CMP0017 OLD)
endif()
+if(POLICY CMP0026)
+ # Allow use of the LOCATION property
+ cmake_policy(SET CMP0026 OLD)
+endif()
+
project(REACTOS)
# Versioning
#include <winbase.h>
#include <winuser.h>
#include <wincon.h>
+#include <strsafe.h>
#include "help.h"
#include "resource.h"
/*
* 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);
}
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;
}
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;
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;
LVText,
i,
k);
- if (LVText != NULL)
+ if (_tcslen(LVText))
{
WriteFile(hFile,
LVText,
}
}
WriteFile(hFile,
- &newl,
- sizeof(TCHAR),
+ newl,
+ sizeof(newl),
&dwWritten,
NULL);
}
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) )
{
0,
(LPARAM)lpProgStr);
- HeapFree(GetProcessHeap(),
- 0,
- lpProgStr);
+ LocalFree(lpProgStr);
}
/* Finally, show and update the progress dialog */
{
hButton = GetDlgItem(hwndDlg, IDC_START);
EnableWindow (hButton, TRUE);
- HeapFree(GetProcessHeap(), 0, lpServiceConfig);
}
else if ( (Flags & SERVICE_ACCEPT_STOP) && (State == SERVICE_RUNNING) )
{
EnableWindow (hButton, TRUE);
}
+ if(lpServiceConfig)
+ HeapFree(GetProcessHeap(), 0, lpServiceConfig);
+
hButton = GetDlgItem(hwndDlg, IDC_START_PARAM);
EnableWindow(hButton, (State == SERVICE_STOPPED));
HeapFree(ProcessHeap,
0,
Info->pAllServices);
+ Info->pAllServices = NULL;
}
ScHandle = OpenSCManager(NULL,
if (ScHandle)
CloseServiceHandle(ScHandle);
- if (!bRet)
+ if (!bRet && Info->pAllServices)
{
HeapFree(ProcessHeap,
0,
LB_ADDSTRING,
0,
(LPARAM)lpServiceConfig->lpDisplayName);
+
+ HeapFree(GetProcessHeap(), 0, lpServiceConfig);
}
/* Move onto the next string */
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)
ULONG value;
INT i;
BOOL Modified = FALSE;
-// BOOL Domain = FALSE;
+#if 0
+ BOOL Domain = FALSE;
+#endif
NET_API_STATUS Status;
INT result = 0;
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);
--- /dev/null
+/*
+ * 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 */
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..."
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..."
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..."
{L"group", unimplemented},
{L"help", cmdHelp},
{L"helpmsg", cmdHelpMsg},
- {L"localgroup", unimplemented},
+ {L"localgroup", cmdLocalGroup},
{L"name", unimplemented},
{L"pause", cmdPause},
{L"print", unimplemented},
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);
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));
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)
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);
*/
/* 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);
}
LoadSettings();
/* Initialize perf data */
- if (!PerfDataInitialize()) {
+ if (!PerfDataInitialize())
+ {
return -1;
}
_tcscat(TempSrc,_T(".decrypt"));
if (!CopyFileEx(source, TempSrc, NULL, NULL, FALSE, COPY_FILE_ALLOW_DECRYPTED_DESTINATION))
{
+ CloseHandle (hFileSrc);
nErrorLevel = 1;
return 0;
}
/* Check Breaker */
if (CheckCtrlBreak(BREAK_INPUT))
{
+ FindClose(hFile);
freep(arg);
return 1;
}
if (_tcscmp(tmpDestPath, _T("\\\\.\\")) &&
!IsExistingDirectory(tmpDestPath))
{
+ FindClose(hFile);
ConOutFormatMessage(GetLastError(), szSrcPath);
freep(arg);
nErrorLevel = 1;
{
SetFileAttributes(TempFileName,FILE_ATTRIBUTE_NORMAL);
if (!DeleteFile(TempFileName))
+ {
+ FindClose (hFile);
return 0;
+ }
}
}while (FindNextFile (hFile, &f));
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;
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];
FindNextFile (hFile, &findBuffer));
FindClose (hFile);
+ if(hDestFile && hDestFile != INVALID_HANDLE_VALUE)
+ FindClose(hDestFile);
+
freep (arg);
return 0;
}
else
ConOutResPrintf(STRING_REPLACE_HELP10, dest);
if ( !FilePromptYNA (0))
+ {
+ CloseHandle (hFileSrc);
return 0;
+ }
}
/* Output depending on add flag */
HANDLE hFile;
WIN32_FIND_DATA findBuffer;
- /* Get file handel to the sourcefile(s) */
+ /* Get file handle to the sourcefile(s) */
hFile = FindFirstFile (szSrcPath, &findBuffer);
/*
/* Take next sourcefile if any */
} while(FindNextFile (hFile, &findBuffer));
+ FindClose(hFile);
+
return filesReplaced;
}
/* Get the next handle */
} while(FindNextFile (hFile, &findBuffer));
+ FindClose(hFile);
+
return filesReplaced;
}
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
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);
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
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
) 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
:: 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
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()
&szProblem,
szInfo,
uProblemId);
- LocalFree((HLOCAL)szInfo);
}
else
{
* 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;
}
*/
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;
}
*/
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;
}
*/
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);
}
*/
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);
}
*/
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);
}
*/
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);
}
/*
*/
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;
}
/*
#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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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 */
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,
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 */
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,
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,
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,
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,
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,
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,
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,
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,
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,
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;
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)
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.@)
*
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;
}
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;
}
#include "setupapi_private.h"
#include <wingdi.h>
+#include <shellapi.h>
/* Unicode constants */
static const WCHAR BackSlash[] = {'\\',0};
};
#undef ADD_PARAM_HANDLER
+#define UNKNOWN_ICON_INDEX 18
/***********************************************************************
* SetupDiDestroyClassImageList(SETUPAPI.@)
return rc;
}
-/***********************************************************************
- * SetupDiGetClassImageIndex (SETUPAPI.@)
- */
static BOOL
SETUP_GetIconIndex(
IN HKEY hClassKey,
return ret;
}
+/***********************************************************************
+ * SetupDiGetClassImageIndex (SETUPAPI.@)
+ */
BOOL WINAPI
SetupDiGetClassImageIndex(
IN PSP_CLASSIMAGELIST_DATA ClassImageListData,
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.@)
*/
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 */
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;
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;
/*
* 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)
*/
{
if (pFcb->Flags & FCB_DELETE_PENDING)
{
- VfatDelEntry(DeviceExt, pFcb);
+ VfatDelEntry(DeviceExt, pFcb, NULL);
FsRtlNotifyFullReportChange(DeviceExt->NotifySync,
&(DeviceExt->NotifyList),
*/
/*
* 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 *****************************************************************/
PUNICODE_STRING PathNameU,
PFILE_OBJECT FileObject,
ULONG RequestedDisposition,
- BOOLEAN OpenTargetDir,
PVFATFCB *ParentFcb)
{
PVFATFCB Fcb;
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);
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;
}
/* 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
/* 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;
/* 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;
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))
{
/*
* 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)
*
*/
}
}
+/*
+ * 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
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;
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)
{
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);
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);
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))
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;
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 */
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;
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;
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);
}
/*
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;
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;
}
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;
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 */
/*
-* 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 */
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)
vfatFCBIsDirectory(
PVFATFCB FCB)
{
- return *FCB->Attributes & FILE_ATTRIBUTE_DIRECTORY;
+ return ((*FCB->Attributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
}
BOOLEAN
PDEVICE_EXTENSION pVCB,
PVFATFCB pFCB)
{
- HASHENTRY* entry;
- ULONG Index;
- ULONG ShortIndex;
PVFATFCB tmpFcb;
DPRINT("releasing FCB at %p: %wZ, refCount:%d\n",
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
}
}
+static
VOID
vfatAddFCBToTable(
PDEVICE_EXTENSION pVCB,
}
}
+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,
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));
}
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))
vfatAddFCBToTable(vcb, rcFCB);
*fileFCB = rcFCB;
- ExFreePool(PathNameBuffer);
+ ExFreePool(NameU.Buffer);
return STATUS_SUCCESS;
}
/*
* 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)
*
*/
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
*/
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);
}
}
break;
case FileRenameInformation:
- Status = STATUS_NOT_IMPLEMENTED;
+ Status = VfatSetRenameInformation(IrpContext->FileObject,
+ FCB,
+ IrpContext->DeviceExt,
+ SystemBuffer,
+ IrpContext->Stack->Parameters.SetFile.FileObject);
break;
default:
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);
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 */
PVFATFCB* Fcb,
PVFATFCB ParentFcb,
ULONG RequestedOptions,
- UCHAR ReqAttr);
+ UCHAR ReqAttr,
+ PVFAT_MOVE_CONTEXT MoveContext);
NTSTATUS
VfatUpdateEntry(
NTSTATUS
VfatDelEntry(
PDEVICE_EXTENSION,
- PVFATFCB);
+ PVFATFCB,
+ PVFAT_MOVE_CONTEXT);
BOOLEAN
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
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);
PDEVICE_EXTENSION pVCB,
PVFATFCB pFCB);
-VOID
-vfatAddFCBToTable(
- PDEVICE_EXTENSION pVCB,
- PVFATFCB pFCB);
-
PVFATFCB
vfatGrabFCBFromTable(
PDEVICE_EXTENSION pDeviceExt,
}
SecurityContext = &AccessState->SubjectSecurityContext;
- SeLockSubjectContext(&AccessState->SubjectSecurityContext);
+ SeLockSubjectContext(SecurityContext);
- Status = SeAssignSecurity(0,
+ Status = SeAssignSecurity(NULL,
AccessState->SecurityDescriptor,
&SecurityDescriptor,
- 0,
+ FALSE,
SecurityContext,
IoGetFileObjectGenericMapping(),
PagedPool);
Status = ObLogSecurityDescriptor(SecurityDescriptor,
&CachedSecurityDescriptor,
1);
- ExFreePool(SecurityDescriptor);
+ ExFreePoolWithTag(SecurityDescriptor, 0);
if (!NT_SUCCESS(Status))
{
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;
}
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;
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=;
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;
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;
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)
ULONG Count);
#endif
-VOID
-NtfsDateTimeToFileTime(ULONGLONG NtfsTime,
- PLARGE_INTEGER SystemTime);
-
VOID
NtfsFileFlagsToAttributes(ULONG NtfsAttributes,
PULONG FileAttributes);
FCB->Recv.Window,
FCB->Recv.Size,
FCB->AddressFrom,
- &FCB->ReceiveIrp.Iosb,
PacketSocketRecvComplete,
FCB);
TDI_RECEIVE_NORMAL,
FCB->Recv.Window,
FCB->Recv.Size,
- &FCB->ReceiveIrp.Iosb,
ReceiveComplete,
FCB );
FCB->Connection.Object,
FCB->ConnectCallInfo,
FCB->ConnectReturnInfo,
- &FCB->ConnectIrp.Iosb,
StreamSocketConnectComplete,
FCB );
}
FCB->Connection.Object,
&FCB->ListenIrp.ConnectionCallInfo,
&FCB->ListenIrp.ConnectionReturnInfo,
- &FCB->ListenIrp.Iosb,
ListenComplete,
FCB );
FCB->Connection.Object,
&FCB->ListenIrp.ConnectionCallInfo,
&FCB->ListenIrp.ConnectionReturnInfo,
- &FCB->ListenIrp.Iosb,
ListenComplete,
FCB );
FCB->Connection.Object,
&FCB->DisconnectTimeout,
FCB->DisconnectFlags,
- &FCB->DisconnectIrp.Iosb,
DisconnectComplete,
FCB,
FCB->ConnectCallInfo,
TDI_RECEIVE_NORMAL,
FCB->Recv.Window + FCB->Recv.Content,
FCB->Recv.Size - FCB->Recv.Content,
- &FCB->ReceiveIrp.Iosb,
ReceiveComplete,
FCB );
}
FCB->Recv.Window,
FCB->Recv.Size,
FCB->AddressFrom,
- &FCB->ReceiveIrp.Iosb,
PacketSocketRecvComplete,
FCB );
}
PFILE_OBJECT ConnectionObject,
PTDI_CONNECTION_INFORMATION ConnectionCallInfo,
PTDI_CONNECTION_INFORMATION ConnectionReturnInfo,
- PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext)
/*
DeviceObject, /* Device object */
ConnectionObject, /* File object */
NULL, /* Event */
- Iosb); /* Status */
+ NULL); /* Status */
if (!*Irp) {
return STATUS_INSUFFICIENT_RESOURCES;
}
ConnectionCallInfo, /* Request connection information */
ConnectionReturnInfo); /* Return connection information */
- TdiCall(*Irp, DeviceObject, NULL, Iosb);
+ TdiCall(*Irp, DeviceObject, NULL, NULL);
return STATUS_PENDING;
}
PFILE_OBJECT ConnectionObject,
PTDI_CONNECTION_INFORMATION *RequestConnectionInfo,
PTDI_CONNECTION_INFORMATION *ReturnConnectionInfo,
- PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext)
/*
DeviceObject, /* Device object */
ConnectionObject, /* File object */
NULL, /* Event */
- Iosb); /* Status */
+ NULL); /* Status */
if (*Irp == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
*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;
}
USHORT Flags,
PCHAR Buffer,
UINT BufferLength,
- PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext)
{
DeviceObject, /* Device object */
TransportObject, /* File object */
NULL, /* Event */
- Iosb); /* Status */
+ NULL); /* Status */
if (!*Irp) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
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. */
USHORT Flags,
PCHAR Buffer,
UINT BufferLength,
- PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext)
{
DeviceObject, /* Device object */
TransportObject, /* File object */
NULL, /* Event */
- Iosb); /* Status */
+ NULL); /* Status */
if (!*Irp) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
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. */
PCHAR Buffer,
UINT BufferLength,
PTDI_CONNECTION_INFORMATION Addr,
- PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext)
/*
DeviceObject, /* Device object */
TransportObject, /* File object */
NULL, /* Event */
- Iosb); /* Status */
+ NULL); /* Status */
if (!*Irp) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
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. */
PCHAR Buffer,
UINT BufferLength,
PTDI_CONNECTION_INFORMATION Addr,
- PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext)
/*
DeviceObject, /* Device object */
TransportObject, /* File object */
NULL, /* Event */
- Iosb); /* Status */
+ NULL); /* Status */
if (!*Irp) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
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. */
PFILE_OBJECT TransportObject,
PLARGE_INTEGER Time,
USHORT Flags,
- PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext,
PTDI_CONNECTION_INFORMATION RequestConnectionInfo,
DeviceObject, /* Device object */
TransportObject, /* File object */
NULL, /* Event */
- Iosb); /* Status */
+ NULL); /* Status */
if (!*Irp) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
RequestConnectionInfo, /* Indication of who to disconnect */
ReturnConnectionInfo); /* Indication of who disconnected */
- TdiCall(*Irp, DeviceObject, NULL, Iosb);
+ TdiCall(*Irp, DeviceObject, NULL, NULL);
return STATUS_PENDING;
}
0,
FCB->Send.Window,
FCB->Send.BytesUsed,
- &FCB->SendIrp.Iosb,
SendComplete,
FCB );
}
SendReq->BufferArray[0].buf,
SendReq->BufferArray[0].len,
TargetAddress,
- &FCB->SendIrp.Iosb,
PacketSocketSendComplete,
FCB);
}
0,
FCB->Send.Window,
FCB->Send.BytesUsed,
- &FCB->SendIrp.Iosb,
SendComplete,
FCB);
}
SendReq->BufferArray[0].buf,
SendReq->BufferArray[0].len,
TargetAddress,
- &FCB->SendIrp.Iosb,
PacketSocketSendComplete,
FCB);
}
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;
PFILE_OBJECT ConnectionObject,
PTDI_CONNECTION_INFORMATION *RequestConnectionInfo,
PTDI_CONNECTION_INFORMATION *ReturnConnectionInfo,
- PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext);
USHORT Flags,
PCHAR Buffer,
UINT BufferLength,
- PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext);
USHORT Flags,
PCHAR Buffer,
UINT BufferLength,
- PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext);
PCHAR Buffer,
UINT BufferLength,
PTDI_CONNECTION_INFORMATION From,
- PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext);
PCHAR Buffer,
UINT BufferLength,
PTDI_CONNECTION_INFORMATION To,
- PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext);
PFILE_OBJECT ConnectionObject,
PTDI_CONNECTION_INFORMATION ConnectionCallInfo,
PTDI_CONNECTION_INFORMATION ConnectionReturnInfo,
- PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext );
PFILE_OBJECT TransportObject,
PLARGE_INTEGER Time,
USHORT Flags,
- PIO_STATUS_BLOCK Iosb,
PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID CompletionContext,
PTDI_CONNECTION_INFORMATION RequestConnectionInfo,
deviceExtension->FullIdentifyData.NVCache_Version
));
- KdPrint2((PRINT_PREFIX "R-rate %#x\n",
+ KdPrint2((PRINT_PREFIX "R-rate %d\n",
deviceExtension->FullIdentifyData.NominalMediaRotationRate
));
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;
((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;
chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
goto CompleteRequest;
}
+continue_read_drq:
// Ensure that this is a read command.
if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
}
}
}
-
} else {
KdPrint2((PRINT_PREFIX
"IdeIntr: Read %#x Dwords\n", wordCount/2));
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;
+ }
}
}
// Adjust buffer address and words left count.
AtaReq->WordsLeft -= wordCount;
AtaReq->DataBuffer += wordCount;
+ AtaReq->WordsTransfered += wordCount;
// Wait for interrupt.
return SRB_STATUS_PENDING;
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)
);
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
);
return;
break; }
- case ATA_PROMISE_ID:
+ case ATA_PROMISE_ID: {
/***********/
/* Promise */
/***********/
+
+ UCHAR sel66 = Channel ? 0x08: 0x02;
+
if(ChipType < PRTX) {
if (isAtapi) {
udmamode =
}
}
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));
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"));
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));
-#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"
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
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
#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 );
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;
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);
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 )
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;
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);
#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
IN LPMIXER_DATA MixerData,
IN PULONG DeviceCount)
{
- MIXER_STATUS Status;
+ MIXER_STATUS Status = MM_STATUS_SUCCESS;
PTOPOLOGY Topology;
ULONG NodeIndex;
LPMIXER_INFO MixerInfo = NULL;
MidiInfo->PinId = PinId;
/* sanity check */
- ASSERT(wcslen(DeviceName) + 1 < MAXPNAMELEN);
+ ASSERT(!DeviceName || (wcslen(DeviceName) + 1 < MAXPNAMELEN));
/* copy device name */
if (bInput && DeviceName)
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;
}
}
/* Check for protected mode */
- if (State->ControlRegisters[0] & FAST486_CR0_PE)
+ if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
{
/* Privilege checks */
}
/* Check for protected mode */
- if (State->ControlRegisters[0] & FAST486_CR0_PE)
+ if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
{
/* Privilege checks */
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;
/* [BX + SI] */
ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBX].LowWord
+ State->GeneralRegs[FAST486_REG_ESI].LowWord;
-
break;
}
/* [BX + DI] */
ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBX].LowWord
+ State->GeneralRegs[FAST486_REG_EDI].LowWord;
-
break;
}
/* SS:[BP + SI] */
ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBP].LowWord
+ State->GeneralRegs[FAST486_REG_ESI].LowWord;
-
break;
}
/* SS:[BP + DI] */
ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBP].LowWord
+ State->GeneralRegs[FAST486_REG_EDI].LowWord;
-
break;
}
{
/* [SI] */
ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_ESI].LowWord;
-
break;
}
{
/* [DI] */
ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EDI].LowWord;
-
break;
}
{
/* [BX] */
ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBX].LowWord;
-
break;
}
}
{
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"
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
Fast486ExtOpcodeMovzxByte, /* 0xB6 - 0xB7 */
Fast486ExtOpcodeMovzxWord,
Fast486ExtOpcodeInvalid, /* 0xB8 */ // Invalid
- Fast486OpcodeGroup0FB9, /* 0xB9 */
- Fast486OpcodeGroup0FBA, /* 0xBA */
+ Fast486ExtOpcodeGroup0FB9, /* 0xB9 */
+ Fast486ExtOpcodeGroup0FBA, /* 0xBA */
Fast486ExtOpcodeBtc, /* 0xBB */
Fast486ExtOpcodeBsf, /* 0xBC */
Fast486ExtOpcodeBsr, /* 0xBD */
/* Main execution loop */
do
{
-NextInst:
if (!State->Halted)
{
+NextInst:
/* Check if this is a new instruction */
if (State->PrefixFlags == 0) State->SavedInstPtr = State->InstPtr;
/* 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;
return TRUE;
}
-FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F00)
+
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F00)
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
}
}
-FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F01)
{
// FAST486_TABLE_REG TableReg;
UCHAR TableReg[6];
}
}
-FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FB9)
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0FB9)
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
return FALSE;
}
-FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FBA)
+FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0FBA)
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN OperandSize, AddressSize;
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_
/* Clear what's left */
NumberToClear &= (_BITCOUNT - 1);
- Mask = MAXINDEX << NumberToClear;
- *Buffer &= Mask;
+ if (NumberToClear)
+ {
+ Mask = MAXINDEX << NumberToClear;
+ *Buffer &= Mask;
+ }
}
VOID
/* Set what's left */
NumberToSet &= (_BITCOUNT - 1);
- Mask = MAXINDEX << NumberToSet;
- *Buffer |= ~Mask;
+ if (NumberToSet)
+ {
+ Mask = MAXINDEX << NumberToSet;
+ *Buffer |= ~Mask;
+ }
}
BOOLEAN
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
VOID
NTAPI
-MiInitializeSpecialPool();
+MiInitializeSpecialPool(VOID);
BOOLEAN
NTAPI
MmIsSpecialPoolAddress(
IN PVOID P);
+BOOLEAN
+NTAPI
+MmIsSpecialPoolAddressFree(
+ IN PVOID P);
+
PVOID
NTAPI
MmAllocateSpecialPool(
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
}
//
- // 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;
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
//
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);
}
/*
//
// Allocate the pool
//
- return ExAllocatePoolWithQuotaTag(PoolType, NumberOfBytes, 'enoN');
+ return ExAllocatePoolWithQuotaTag(PoolType, NumberOfBytes, TAG_NONE);
}
/*
/* 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 */
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());
(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 */
#define MODULE_INVOLVED_IN_ARM3
#include "../ARM3/miarm.h"
+extern ULONG ExpPoolFlags;
extern PMMPTE MmSystemPteBase;
PMMPTE
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;
(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;
/* 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 */
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;
/* Save extra values */
MiSpecialPoolExtra = PointerPte;
- MiSpecialPoolExtraCount = SpecialPoolPtes - 1024;
+ MiSpecialPoolExtraCount = SpecialPoolPtes - PTE_PER_PAGE;
/* Mark the previous PTE as the last one */
MiSpecialPoolLastPte = PointerPte - 2;
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)
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;
((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 */
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 */
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;
}
/* 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;
/* 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);
}
}
}
LARGE_INTEGER TickCount;
PMMPFN Pfn;
- DPRINT1("MmFreeSpecialPool(%p)\n", P);
+ DPRINT("MmFreeSpecialPool(%p)\n", P);
/* Get the PTE */
PointerPte = MiAddressToPte(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);
}
}
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)
/* 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);
}
}
}
Pfn = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
/* Lock PFN database */
- ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
Irql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
/* Delete this PFN */
/* 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);
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);
0xFB, // sti
- // HACK: The following instruction should be HLT!
- 0x90, // nop
+ 0xF4, // hlt
0xEB, 0xF5, // jmp BOP_SEQ (offset -11)
if (InfoBuffer == NULL)
{
ERR_(VIDEOPRT, "Could not allocate buffer for key info\n");
- return Status;
+ return STATUS_INSUFFICIENT_RESOURCES;
}
}
src += ft_face->glyph->bitmap.pitch;
dst += pitch;
}
- return needed;
+ break;
}
case ft_glyph_format_outline:
{
{
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:
#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))
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
*/
#include <win32k.h>
+DBG_DEFAULT_CHANNEL(UserClass);
/* CALLPROC ******************************************************************/
{
PCLS pCls;
PWND pWnd;
+ PDESKTOP pDesk;
PCALLPROCDATA CallProc = NULL;
PTHREADINFO pti;
// 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);
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;
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 */
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;
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)
{
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,
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! */
}
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;
Class = Class->pclsNext;
}
break;
+#endif
// MSDN:
// hIconSm, A handle to a small icon that is associated with the window 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;
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;
Class = Class->pclsNext;
}
break;
+#endif
case GCLP_HMODULE:
Ret = (ULONG_PTR)Class->hModule;
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. */
/* 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;
}
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 */
}
InsertHeadList(&CurIcon->ProcessList, &Current->ListEntry);
Current->Process = Win32Process;
+ IntReferenceProcessInfo(Win32Process);
return TRUE;
}
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);
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))
/* 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;
}
}
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
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
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)
CurIcon = UserCreateObject(
gHandleTable,
NULL,
- NULL,
+ GetW32ThreadInfo(),
&hCurIcon,
TYPE_CURSOR,
Animated ? sizeof(ACON) : sizeof(CURICON_OBJECT));
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;
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;
}
/*
_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;
}
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:
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;
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);
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;
}
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);
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);
{
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 );
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))
{
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);
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
{
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;
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;
{
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 */
}
{
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);
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)
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;
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();
pti->pClientInfo->dwTIFlags = pti->TIF_flags;
}
W32Process->W32PF_flags &= ~W32PF_WAITFORINPUTIDLE;
+ IntDereferenceProcessInfo(W32Process);
ObDereferenceObject(Process);
UserLeave();
return Status;
{
/* 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,
return ObjHead;
}
-static void FreeProcMarkObject(
+void FreeProcMarkObject(
_In_ PVOID Object)
{
PPROCESSINFO ppi = ((PPROCMARKHEAD)Object)->ppi;
{ 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 */
return object;
}
+#ifndef NEW_CURSORICON
VOID
FASTCALL
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)
if (Entry->flags & HANDLEENTRY_INDESTROY)
continue;
+#ifndef NEW_CURSORICON
/* Spcial case for cursors until cursoricon_new is there */
if (Entry->type == TYPE_CURSOR)
{
}
continue;
}
+#endif
/* Call destructor */
if (!ObjectCallbacks[Entry->type].ObjectDestroy(Entry->ptr))
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);
UserDereferenceObject(obj);
}
+void FreeProcMarkObject(_In_ PVOID Object);
+
/* EOF */
{
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)
{
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 );
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;
if (Dce->hrgnClip != NULL)
RgnClip = REGION_LockRgn(Dce->hrgnClip);
-
+
if (RgnClip)
{
IntGdiCombineRgn(RgnVisible, RgnVisible, RgnClip, RGN_AND);
#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
}
BOOL bUpdateVisRgn = TRUE;
HDC hDC = NULL;
PPROCESSINFO ppi;
- PLIST_ENTRY pLE;
+ PLIST_ENTRY ListEntry;
if (NULL == Wnd)
{
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;
}
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.
break;
}
}
- pLE = Dce->List.Flink;
- Dce = CONTAINING_RECORD(pLE, DCE, List);
}
- while (pLE != &LEDce);
KeLeaveCriticalRegion();
Dce = (DceEmpty == NULL) ? DceUnused : DceEmpty;
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)) &&
* 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 )
/***********************************************************************
* 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;
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;
}
/***********************************************************************
DceFreeWindowDCE(PWND Window)
{
PDCE pDCE;
- PLIST_ENTRY pLE;
+ PLIST_ENTRY ListEntry;
if (DCECount <= 0)
{
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) )
{
}
else if (Window->pcls->style & CS_OWNDC) /* Owned DCE */
{
- pDCE = DceFreeDCE(pDCE, FALSE);
- if (!pDCE) break;
+ DceFreeDCE(pDCE, FALSE);
continue;
}
else
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
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)
CurrentWindow = UserGetWindowObject(pDCE->hwndCurrent);
if (NULL == CurrentWindow)
{
- pLE = pDCE->List.Flink;
- pDCE = CONTAINING_RECORD(pLE, DCE, List);
continue;
}
}
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))
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)
Ret = Dce->hwndCurrent;
break;
}
- pLE = Dce->List.Flink;
- Dce = CONTAINING_RECORD(pLE, DCE, List);
}
- while (pLE != &LEDce);
return Ret;
}
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))
{
}
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,
TRACE("IntCreateWindow hIconSmIntern %p\n",Class->hIconSmIntern);
Class->CSF_flags |= CSF_CACHEDSMICON;
}
+#endif
if (pWnd->pcls->CSF_flags & CSF_SERVERSIDEPROC)
pWnd->state |= WNDS_SERVERSIDEWINDOWPROC;
}
Ret = NtUserSystemParametersInfo(SPI_SETDESKWALLPAPER, uiParam, pvParam, fWinIni);
- RtlFreeUnicodeString(&ustrWallpaper);
+
+ if (pvParam)
+ RtlFreeUnicodeString(&ustrWallpaper);
+
return Ret;
}
}
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;
/* 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);
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;
/* 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);
case WM_RBUTTONUP:
{
POINT Pt;
- if (hWnd == GetCapture())
- {
- ReleaseCapture();
- }
+
Pt.x = GET_X_LPARAM(lParam);
Pt.y = GET_Y_LPARAM(lParam);
ClientToScreen(hWnd, &Pt);