Author: ion
Date: Sun Nov 6 15:34:39 2011
New Revision: 54316
URL:
http://svn.reactos.org/svn/reactos?rev=54316&view=rev
Log:
[KERNEL32]: Reimplement GetLong/ShortPathNameA to get rid of Wineisms and fix the fact
they were forcing paths to MAX_PATH when doing A->W->A conversion. The correct
behavior is to call W to get the true, real path length (no matter how big), and then deal
with the sizing issues when downconverting back to A.
Modified:
trunk/reactos/dll/win32/kernel32/client/path.c
Modified: trunk/reactos/dll/win32/kernel32/client/path.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/path.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/client/path.c [iso-8859-1] Sun Nov 6 15:34:39 2011
@@ -282,152 +282,6 @@
lpBuffer,
lpFilePart) / sizeof(WCHAR);
}
-
-
-/*
- * NOTE: Copied from Wine.
- * @implemented
- */
-DWORD
-WINAPI
-GetShortPathNameA (
- LPCSTR longpath,
- LPSTR shortpath,
- DWORD shortlen
- )
-{
- PWCHAR LongPathW;
- WCHAR ShortPathW[MAX_PATH];
- DWORD ret;
-
- if (!longpath)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return 0;
- }
-
- if (!(LongPathW = FilenameA2W(longpath, FALSE)))
- return 0;
-
- ret = GetShortPathNameW(LongPathW, ShortPathW, MAX_PATH);
-
- if (!ret)
- return 0;
-
- if (ret > MAX_PATH)
- {
- SetLastError(ERROR_FILENAME_EXCED_RANGE);
- return 0;
- }
-
- return FilenameW2A_FitOrFail(shortpath, shortlen, ShortPathW, ret+1);
-}
-
-
-/*
- * NOTE: Copied from Wine.
- * @implemented
- */
-DWORD
-WINAPI
-GetShortPathNameW (
- LPCWSTR longpath,
- LPWSTR shortpath,
- DWORD shortlen
- )
-{
- WCHAR tmpshortpath[MAX_PATH];
- LPCWSTR p;
- DWORD sp = 0, lp = 0;
- DWORD tmplen;
- WIN32_FIND_DATAW wfd;
- HANDLE goit;
- UNICODE_STRING ustr;
- WCHAR ustr_buf[8+1+3+1];
-
- DPRINT("GetShortPathNameW: %S\n",longpath);
-
- if (!longpath)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return 0;
- }
- if (!longpath[0])
- {
- SetLastError(ERROR_BAD_PATHNAME);
- return 0;
- }
-
- /* check for drive letter */
- if (longpath[0] != '/' && longpath[1] == ':' )
- {
- tmpshortpath[0] = longpath[0];
- tmpshortpath[1] = ':';
- sp = lp = 2;
- }
-
- ustr.Buffer = ustr_buf;
- ustr.Length = 0;
- ustr.MaximumLength = sizeof(ustr_buf);
-
- while (longpath[lp])
- {
- /* check for path delimiters and reproduce them */
- if (longpath[lp] == '\\' || longpath[lp] == '/')
- {
- if (!sp || tmpshortpath[sp-1] != '\\')
- {
- /* strip double "\\" */
- tmpshortpath[sp] = '\\';
- sp++;
- }
- tmpshortpath[sp] = 0; /* terminate string */
- lp++;
- continue;
- }
-
- for (p = longpath + lp; *p && *p != '/' && *p !=
'\\'; p++);
- tmplen = p - (longpath + lp);
- lstrcpynW(tmpshortpath + sp, longpath + lp, tmplen + 1);
- /* Check, if the current element is a valid dos name */
- if (tmplen <= 8+1+3)
- {
- BOOLEAN spaces;
- memcpy(ustr_buf, longpath + lp, tmplen * sizeof(WCHAR));
- ustr_buf[tmplen] = '\0';
- ustr.Length = (USHORT)tmplen * sizeof(WCHAR);
- if (RtlIsNameLegalDOS8Dot3(&ustr, NULL, &spaces) && !spaces)
- {
- sp += tmplen;
- lp += tmplen;
- continue;
- }
- }
-
- /* Check if the file exists and use the existing short file name */
- goit = FindFirstFileW(tmpshortpath, &wfd);
- if (goit == INVALID_HANDLE_VALUE) goto notfound;
- FindClose(goit);
- lstrcpyW(tmpshortpath + sp, wfd.cAlternateFileName);
- sp += lstrlenW(tmpshortpath + sp);
- lp += tmplen;
- }
- tmpshortpath[sp] = 0;
-
- tmplen = lstrlenW(tmpshortpath) + 1;
- if (tmplen <= shortlen)
- {
- lstrcpyW(shortpath, tmpshortpath);
- tmplen--; /* length without 0 */
- }
-
- return tmplen;
-
- notfound:
- SetLastError ( ERROR_FILE_NOT_FOUND );
- return 0;
-}
-
/*
* @implemented
@@ -786,32 +640,271 @@
return tmplen;
}
-
-
-/***********************************************************************
- * GetLongPathNameA (KERNEL32.@)
- */
-DWORD WINAPI GetLongPathNameA( LPCSTR shortpath, LPSTR longpath, DWORD longlen )
-{
- WCHAR *shortpathW;
- WCHAR longpathW[MAX_PATH];
- DWORD ret;
-
- DPRINT("GetLongPathNameA %s, %i\n",shortpath,longlen );
-
- if (!(shortpathW = FilenameA2W( shortpath, FALSE )))
- return 0;
-
- ret = GetLongPathNameW(shortpathW, longpathW, MAX_PATH);
-
- if (!ret) return 0;
- if (ret > MAX_PATH)
- {
- SetLastError(ERROR_FILENAME_EXCED_RANGE);
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
+GetLongPathNameA(IN LPCSTR lpszShortPath,
+ IN LPSTR lpszLongPath,
+ IN DWORD cchBuffer)
+{
+ ULONG Result, PathLength;
+ PWCHAR LongPath;
+ NTSTATUS Status;
+ UNICODE_STRING LongPathUni, ShortPathUni;
+ ANSI_STRING LongPathAnsi;
+ WCHAR LongPathBuffer[MAX_PATH];
+
+ LongPath = NULL;
+ LongPathAnsi.Buffer = NULL;
+ ShortPathUni.Buffer = NULL;
+ Result = 0;
+
+ if (!lpszShortPath)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
-
- return FilenameW2A_FitOrFail(longpath, longlen, longpathW, ret+1 );
+
+ Status = Basep8BitStringToDynamicUnicodeString(&ShortPathUni, lpszShortPath);
+ if (!NT_SUCCESS(Status)) goto Quickie;
+
+ LongPath = LongPathBuffer;
+
+ PathLength = GetLongPathNameW(ShortPathUni.Buffer, LongPathBuffer, MAX_PATH);
+ if (PathLength >= MAX_PATH)
+ {
+ LongPath = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathLength * sizeof(WCHAR));
+ if (!LongPath)
+ {
+ PathLength = 0;
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ }
+ else
+ {
+ PathLength = GetLongPathNameW(ShortPathUni.Buffer, LongPath, PathLength);
+ }
+ }
+
+ if (!PathLength) goto Quickie;
+
+ ShortPathUni.MaximumLength = PathLength * sizeof(WCHAR) + sizeof(UNICODE_NULL);
+ LongPathUni.Buffer = LongPath;
+ LongPathUni.Length = PathLength * sizeof(WCHAR);
+
+ Status = BasepUnicodeStringTo8BitString(&LongPathAnsi, &LongPathUni, TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ BaseSetLastNTError(Status);
+ Result = 0;
+ }
+
+ Result = LongPathAnsi.Length;
+ if ((lpszLongPath) && (cchBuffer > LongPathAnsi.Length))
+ {
+ RtlMoveMemory(lpszLongPath, LongPathAnsi.Buffer, LongPathAnsi.Length);
+ lpszLongPath[Result] = ANSI_NULL;
+ }
+ else
+ {
+ Result = LongPathAnsi.Length + sizeof(ANSI_NULL);
+ }
+
+Quickie:
+ if (ShortPathUni.Buffer) RtlFreeUnicodeString(&ShortPathUni);
+ if (LongPathAnsi.Buffer) RtlFreeAnsiString(&LongPathAnsi);
+ if ((LongPath) && (LongPath != LongPathBuffer))
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, LongPath);
+ }
+ return Result;
+}
+
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
+GetShortPathNameA(IN LPCSTR lpszLongPath,
+ IN LPSTR lpszShortPath,
+ IN DWORD cchBuffer)
+{
+ ULONG Result, PathLength;
+ PWCHAR ShortPath;
+ NTSTATUS Status;
+ UNICODE_STRING LongPathUni, ShortPathUni;
+ ANSI_STRING ShortPathAnsi;
+ WCHAR ShortPathBuffer[MAX_PATH];
+
+ ShortPath = NULL;
+ ShortPathAnsi.Buffer = NULL;
+ LongPathUni.Buffer = NULL;
+ Result = 0;
+
+ if (!lpszLongPath)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+
+ Status = Basep8BitStringToDynamicUnicodeString(&LongPathUni, lpszLongPath);
+ if (!NT_SUCCESS(Status)) goto Quickie;
+
+ ShortPath = ShortPathBuffer;
+
+ PathLength = GetShortPathNameW(LongPathUni.Buffer, ShortPathBuffer, MAX_PATH);
+ if (PathLength >= MAX_PATH)
+ {
+ ShortPath = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathLength * sizeof(WCHAR));
+ if (!ShortPath)
+ {
+ PathLength = 0;
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ }
+ else
+ {
+ PathLength = GetLongPathNameW(LongPathUni.Buffer, ShortPath, PathLength);
+ }
+ }
+
+ if (!PathLength) goto Quickie;
+
+ LongPathUni.MaximumLength = PathLength * sizeof(WCHAR) + sizeof(UNICODE_NULL);
+ ShortPathUni.Buffer = ShortPath;
+ ShortPathUni.Length = PathLength * sizeof(WCHAR);
+
+ Status = BasepUnicodeStringTo8BitString(&ShortPathAnsi, &ShortPathUni,
TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ BaseSetLastNTError(Status);
+ Result = 0;
+ }
+
+ Result = ShortPathAnsi.Length;
+ if ((lpszShortPath) && (cchBuffer > ShortPathAnsi.Length))
+ {
+ RtlMoveMemory(lpszShortPath, ShortPathAnsi.Buffer, ShortPathAnsi.Length);
+ lpszShortPath[Result] = ANSI_NULL;
+ }
+ else
+ {
+ Result = ShortPathAnsi.Length + sizeof(ANSI_NULL);
+ }
+
+Quickie:
+ if (LongPathUni.Buffer) RtlFreeUnicodeString(&LongPathUni);
+ if (ShortPathAnsi.Buffer) RtlFreeAnsiString(&ShortPathAnsi);
+ if ((ShortPath) && (ShortPath != ShortPathBuffer))
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, ShortPath);
+ }
+ return Result;
+}
+
+
+/*
+ * NOTE: Copied from Wine.
+ * @implemented
+ */
+DWORD
+WINAPI
+GetShortPathNameW (
+ LPCWSTR longpath,
+ LPWSTR shortpath,
+ DWORD shortlen
+ )
+{
+ WCHAR tmpshortpath[MAX_PATH];
+ LPCWSTR p;
+ DWORD sp = 0, lp = 0;
+ DWORD tmplen;
+ WIN32_FIND_DATAW wfd;
+ HANDLE goit;
+ UNICODE_STRING ustr;
+ WCHAR ustr_buf[8+1+3+1];
+
+ DPRINT("GetShortPathNameW: %S\n",longpath);
+
+ if (!longpath)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+ if (!longpath[0])
+ {
+ SetLastError(ERROR_BAD_PATHNAME);
+ return 0;
+ }
+
+ /* check for drive letter */
+ if (longpath[0] != '/' && longpath[1] == ':' )
+ {
+ tmpshortpath[0] = longpath[0];
+ tmpshortpath[1] = ':';
+ sp = lp = 2;
+ }
+
+ ustr.Buffer = ustr_buf;
+ ustr.Length = 0;
+ ustr.MaximumLength = sizeof(ustr_buf);
+
+ while (longpath[lp])
+ {
+ /* check for path delimiters and reproduce them */
+ if (longpath[lp] == '\\' || longpath[lp] == '/')
+ {
+ if (!sp || tmpshortpath[sp-1] != '\\')
+ {
+ /* strip double "\\" */
+ tmpshortpath[sp] = '\\';
+ sp++;
+ }
+ tmpshortpath[sp] = 0; /* terminate string */
+ lp++;
+ continue;
+ }
+
+ for (p = longpath + lp; *p && *p != '/' && *p !=
'\\'; p++);
+ tmplen = p - (longpath + lp);
+ lstrcpynW(tmpshortpath + sp, longpath + lp, tmplen + 1);
+ /* Check, if the current element is a valid dos name */
+ if (tmplen <= 8+1+3)
+ {
+ BOOLEAN spaces;
+ memcpy(ustr_buf, longpath + lp, tmplen * sizeof(WCHAR));
+ ustr_buf[tmplen] = '\0';
+ ustr.Length = (USHORT)tmplen * sizeof(WCHAR);
+ if (RtlIsNameLegalDOS8Dot3(&ustr, NULL, &spaces) && !spaces)
+ {
+ sp += tmplen;
+ lp += tmplen;
+ continue;
+ }
+ }
+
+ /* Check if the file exists and use the existing short file name */
+ goit = FindFirstFileW(tmpshortpath, &wfd);
+ if (goit == INVALID_HANDLE_VALUE) goto notfound;
+ FindClose(goit);
+ lstrcpyW(tmpshortpath + sp, wfd.cAlternateFileName);
+ sp += lstrlenW(tmpshortpath + sp);
+ lp += tmplen;
+ }
+ tmpshortpath[sp] = 0;
+
+ tmplen = lstrlenW(tmpshortpath) + 1;
+ if (tmplen <= shortlen)
+ {
+ lstrcpyW(shortpath, tmpshortpath);
+ tmplen--; /* length without 0 */
+ }
+
+ return tmplen;
+
+ notfound:
+ SetLastError ( ERROR_FILE_NOT_FOUND );
+ return 0;
}
/* EOF */