ReactOS.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2025
March
February
January
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
February
List overview
Download
Ros-diffs
February 2025
----- 2025 -----
March 2025
February 2025
January 2025
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
ros-diffs@reactos.org
17 participants
79 discussions
Start a n
N
ew thread
[reactos] 01/01: [SHIMGVW] Display shell context menu for the image on right-click (#7711)
by Whindmar Saksit
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=bc52d5f1f4591dc5b1569…
commit bc52d5f1f4591dc5b15698cccb59b379539aaadf Author: Whindmar Saksit <whindsaks(a)proton.me> AuthorDate: Thu Feb 13 13:13:02 2025 +0100 Commit: GitHub <noreply(a)github.com> CommitDate: Thu Feb 13 13:13:02 2025 +0100 [SHIMGVW] Display shell context menu for the image on right-click (#7711) CORE-13340 --- dll/win32/shimgvw/CMakeLists.txt | 1 + dll/win32/shimgvw/loader.cpp | 18 ++--- dll/win32/shimgvw/shimgvw.c | 23 ++++-- dll/win32/shimgvw/shimgvw.h | 5 ++ dll/win32/shimgvw/util.c | 158 +++++++++++++++++++++++++++++++++++++++ sdk/include/reactos/shellutils.h | 12 +-- 6 files changed, 198 insertions(+), 19 deletions(-) diff --git a/dll/win32/shimgvw/CMakeLists.txt b/dll/win32/shimgvw/CMakeLists.txt index 15983aff150..b9b55c42233 100644 --- a/dll/win32/shimgvw/CMakeLists.txt +++ b/dll/win32/shimgvw/CMakeLists.txt @@ -7,6 +7,7 @@ list(APPEND SOURCE shimgvw.c comsup.c shimgvw.rc + util.c ${CMAKE_CURRENT_BINARY_DIR}/shimgvw_stubs.c ${CMAKE_CURRENT_BINARY_DIR}/shimgvw.def) diff --git a/dll/win32/shimgvw/loader.cpp b/dll/win32/shimgvw/loader.cpp index 50112f6c486..bde8b12ac13 100644 --- a/dll/win32/shimgvw/loader.cpp +++ b/dll/win32/shimgvw/loader.cpp @@ -21,7 +21,7 @@ static HRESULT Read(HANDLE hFile, void* Buffer, DWORD Size) return Size == Transferred ? S_OK : HResultFromWin32(ERROR_HANDLE_EOF); } -struct IMAGEINFO +struct IMAGESTATS { UINT w, h; BYTE bpp; @@ -91,7 +91,7 @@ static BYTE GetPngBppFromIHDRData(const void* buffer) return (depth <= 16 && type <= 6) ? channels[type] * depth : 0; } -static bool GetInfoFromPng(const void* file, SIZE_T size, IMAGEINFO& info) +static bool GetInfoFromPng(const void* file, SIZE_T size, IMAGESTATS& info) { C_ASSERT(sizeof(PNGSIGNATURE) == 8); C_ASSERT(sizeof(PNGSIGANDIHDR) == 8 + (4 + 4 + (4 + 4 + 5) + 4)); @@ -111,7 +111,7 @@ static bool GetInfoFromPng(const void* file, SIZE_T size, IMAGEINFO& info) return false; } -static bool GetInfoFromBmp(const void* pBitmapInfo, IMAGEINFO& info) +static bool GetInfoFromBmp(const void* pBitmapInfo, IMAGESTATS& info) { BitmapInfoHeader bih(pBitmapInfo); info.w = bih.biWidth; @@ -121,11 +121,11 @@ static bool GetInfoFromBmp(const void* pBitmapInfo, IMAGEINFO& info) return info.w && bpp == info.bpp; } -static bool GetInfoFromIcoBmp(const void* pBitmapInfo, IMAGEINFO& stat) +static bool GetInfoFromIcoBmp(const void* pBitmapInfo, IMAGESTATS& info) { - bool ret = GetInfoFromBmp(pBitmapInfo, stat); - stat.h /= 2; // Don't include mask - return ret && stat.h; + bool ret = GetInfoFromBmp(pBitmapInfo, info); + info.h /= 2; // Don't include mask + return ret && info.h; } EXTERN_C PCWSTR GetExtraExtensionsGdipList(VOID) @@ -158,7 +158,7 @@ static void OverrideFileContent(HGLOBAL& hMem, DWORD& Size) for (UINT i = 0; i < count; ++i) { BOOL valid = FALSE; - IMAGEINFO info; + IMAGESTATS info; const BYTE* data = buffer + entries[i].offset; if (IsPngSignature(data, entries[i].size)) valid = GetInfoFromPng(data, entries[i].size, info); @@ -189,7 +189,7 @@ static void OverrideFileContent(HGLOBAL& hMem, DWORD& Size) const BYTE* data = buffer + entries[i].offset; if (IsPngSignature(data, entries[i].size)) { - IMAGEINFO info; + IMAGESTATS info; if (!GetInfoFromPng(data, entries[i].size, info)) continue; bih.biPlanes = 1; diff --git a/dll/win32/shimgvw/shimgvw.c b/dll/win32/shimgvw/shimgvw.c index 7284266b94a..ba8dd000e81 100644 --- a/dll/win32/shimgvw/shimgvw.c +++ b/dll/win32/shimgvw/shimgvw.c @@ -1190,7 +1190,7 @@ ZoomWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_RBUTTONUP: { ZoomWnd_OnButtonUp(hwnd, uMsg, wParam, lParam); - break; + goto doDefault; } case WM_LBUTTONDBLCLK: { @@ -1209,6 +1209,10 @@ ZoomWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) (SHORT)HIWORD(wParam), (UINT)LOWORD(wParam)); break; } + case WM_CONTEXTMENU: + if (Preview_IsMainWnd(pData->m_hwnd)) + DoShellContextMenuOnFile(hwnd, pData->m_szFile, lParam); + break; case WM_HSCROLL: case WM_VSCROLL: ZoomWnd_OnHVScroll(pData, hwnd, wParam, uMsg == WM_VSCROLL); @@ -1230,7 +1234,7 @@ ZoomWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } break; } - default: + default: doDefault: { return DefWindowProcW(hwnd, uMsg, wParam, lParam); } @@ -1429,9 +1433,7 @@ Preview_ToggleSlideShowEx(PPREVIEW_DATA pData, BOOL StartTimer) if (IsWindowVisible(g_hwndFullscreen)) { - KillTimer(g_hwndFullscreen, SLIDESHOW_TIMER_ID); - ShowWindow(g_hMainWnd, SW_SHOW); - ShowWindow(g_hwndFullscreen, SW_HIDE); + Preview_EndSlideShow(g_hwndFullscreen); } else { @@ -1577,6 +1579,10 @@ Preview_OnCommand(HWND hwnd, UINT nCommandID) Preview_Edit(hwnd); break; + case IDC_HELP_TOC: + DisplayHelp(hwnd); + break; + default: break; } @@ -1693,6 +1699,13 @@ PreviewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) Preview_OnDestroy(hwnd); break; } + case WM_CONTEXTMENU: + { + PPREVIEW_DATA pData = Preview_GetData(hwnd); + if ((int)lParam == -1) + return ZoomWndProc(pData->m_hwndZoom, uMsg, wParam, lParam); + break; + } case WM_TIMER: { if (wParam == SLIDESHOW_TIMER_ID) diff --git a/dll/win32/shimgvw/shimgvw.h b/dll/win32/shimgvw/shimgvw.h index c17a15bb8f2..279d08cd244 100644 --- a/dll/win32/shimgvw/shimgvw.h +++ b/dll/win32/shimgvw/shimgvw.h @@ -12,6 +12,7 @@ #define _INC_WINDOWS #define COM_NO_WINDOWS_H #define INITGUID +#define COBJMACROS #include <windef.h> #include <winbase.h> @@ -23,6 +24,7 @@ #include <gdiplus.h> #include <shlwapi.h> #include <strsafe.h> +#include <shobjidl.h> #include <debug.h> @@ -69,6 +71,9 @@ void Anime_Start(PANIME pAnime, DWORD dwDelay); void Anime_Pause(PANIME pAnime); BOOL Anime_OnTimer(PANIME pAnime, WPARAM wParam); +void DoShellContextMenuOnFile(HWND hwnd, PCWSTR File, LPARAM lParam); +void DisplayHelp(HWND hwnd); + static inline LPVOID QuickAlloc(SIZE_T cbSize, BOOL bZero) { return HeapAlloc(GetProcessHeap(), (bZero ? HEAP_ZERO_MEMORY : 0), cbSize); diff --git a/dll/win32/shimgvw/util.c b/dll/win32/shimgvw/util.c new file mode 100644 index 00000000000..290ad083fad --- /dev/null +++ b/dll/win32/shimgvw/util.c @@ -0,0 +1,158 @@ +/* + * PROJECT: ReactOS Picture and Fax Viewer + * LICENSE: GPL-2.0 (
https://spdx.org/licenses/GPL-2.0
) + * PURPOSE: Utility routines + * COPYRIGHT: Copyright 2025 Whindmar Saksit <whindsaks(a)proton.me> + */ + +#include "shimgvw.h" +#include <windowsx.h> +#include <shlobj.h> +#include <shellapi.h> +#include <shellutils.h> +#include <shlwapi_undoc.h> + +IContextMenu *g_pContextMenu = NULL; + +static int +GetMenuItemIdByPos(HMENU hMenu, UINT Pos) +{ + MENUITEMINFOW mii; + mii.cbSize = FIELD_OFFSET(MENUITEMINFOW, hbmpItem); /* USER32 version agnostic */ + mii.fMask = MIIM_ID; + mii.cch = 0; + return GetMenuItemInfoW(hMenu, Pos, TRUE, &mii) ? mii.wID : -1; +} + +static BOOL +IsMenuSeparator(HMENU hMenu, UINT Pos) +{ + MENUITEMINFOW mii; + mii.cbSize = FIELD_OFFSET(MENUITEMINFOW, hbmpItem); /* USER32 version agnostic */ + mii.fMask = MIIM_FTYPE; + mii.cch = 0; + return GetMenuItemInfoW(hMenu, Pos, TRUE, &mii) && (mii.fType & MFT_SEPARATOR); +} + +static BOOL +IsSelfShellVerb(PCWSTR Assoc, PCWSTR Verb) +{ + WCHAR buf[MAX_PATH * 3]; + DWORD cch = _countof(buf); + HRESULT hr = AssocQueryStringW(ASSOCF_NOTRUNCATE, ASSOCSTR_COMMAND, Assoc, Verb, buf, &cch); + return hr == S_OK && *Assoc == L'.' && StrStrW(buf, L",ImageView_Fullscreen"); +} + +static void +ModifyShellContextMenu(IContextMenu *pCM, HMENU hMenu, UINT CmdIdFirst, PCWSTR Assoc) +{ + HRESULT hr; + UINT id, i; + for (i = 0; i < GetMenuItemCount(hMenu); ++i) + { + WCHAR buf[200]; + id = GetMenuItemIdByPos(hMenu, i); + if (id == (UINT)-1) + continue; + + *buf = UNICODE_NULL; + /* Note: We just ask for the wide string because all the items we care about come from shell32 and it handles both */ + hr = IContextMenu_GetCommandString(pCM, id - CmdIdFirst, GCS_VERBW, NULL, (char*)buf, _countof(buf)); + if (SUCCEEDED(hr)) + { + UINT remove = FALSE; + if (IsSelfShellVerb(Assoc, buf)) + ++remove; + else if (!lstrcmpiW(L"cut", buf) || !lstrcmpiW(L"copy", buf) || !lstrcmpiW(L"link", buf)) + ++remove; + + if (remove && DeleteMenu(hMenu, i, MF_BYPOSITION)) + { + if (i-- > 0) + { + if (IsMenuSeparator(hMenu, i) && IsMenuSeparator(hMenu, i + 1)) + DeleteMenu(hMenu, i, MF_BYPOSITION); + } + } + } + } + + while (IsMenuSeparator(hMenu, 0) && DeleteMenu(hMenu, 0, MF_BYPOSITION)) {} +} + +static LRESULT CALLBACK +ShellContextMenuWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + LRESULT lRes = 0; + if (FAILED(SHForwardContextMenuMsg((IUnknown*)g_pContextMenu, uMsg, wParam, lParam, &lRes, TRUE))) + lRes = DefWindowProc(hwnd, uMsg, wParam, lParam); + return lRes; +} + +static void +DoShellContextMenu(HWND hwnd, IContextMenu *pCM, PCWSTR File, LPARAM lParam) +{ + enum { first = 1, last = 0x7fff }; + HRESULT hr; + HMENU hMenu = CreatePopupMenu(); + UINT cmf = GetKeyState(VK_SHIFT) < 0 ? CMF_EXTENDEDVERBS : 0; + + POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + if ((int)lParam == -1) + { + RECT rect; + GetWindowRect(hwnd, &rect); + pt.x = (rect.left + rect.right) / 2; + pt.y = rect.top; + } + + g_pContextMenu = pCM; + hwnd = SHCreateWorkerWindowW(ShellContextMenuWindowProc, hwnd, 0, WS_VISIBLE | WS_CHILD, NULL, 0); + if (!hwnd) + goto die; + hr = IContextMenu_QueryContextMenu(pCM, hMenu, 0, first, last, cmf | CMF_NODEFAULT); + if (SUCCEEDED(hr)) + { + UINT id; + ModifyShellContextMenu(pCM, hMenu, first, PathFindExtensionW(File)); + id = TrackPopupMenuEx(hMenu, TPM_RETURNCMD, pt.x, pt.y, hwnd, NULL); + if (id) + { + UINT flags = (GetKeyState(VK_SHIFT) < 0 ? CMIC_MASK_SHIFT_DOWN : 0) | + (GetKeyState(VK_CONTROL) < 0 ? CMIC_MASK_CONTROL_DOWN : 0); + CMINVOKECOMMANDINFO ici = { sizeof(ici), flags, hwnd, MAKEINTRESOURCEA(id - first) }; + ici.nShow = SW_SHOW; + hr = IContextMenu_InvokeCommand(pCM, &ici); + } + } + DestroyWindow(hwnd); +die: + DestroyMenu(hMenu); + g_pContextMenu = NULL; +} + +void +DoShellContextMenuOnFile(HWND hwnd, PCWSTR File, LPARAM lParam) +{ + HRESULT hr; + IShellFolder *pSF; + PCUITEMID_CHILD pidlItem; + PIDLIST_ABSOLUTE pidl = ILCreateFromPath(File); + if (pidl && SUCCEEDED(SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &pSF), &pidlItem))) + { + IContextMenu *pCM; + hr = IShellFolder_GetUIObjectOf(pSF, hwnd, 1, &pidlItem, &IID_IContextMenu, NULL, (void**)&pCM); + if (SUCCEEDED(hr)) + { + DoShellContextMenu(hwnd, pCM, File, lParam); + IContextMenu_Release(pCM); + } + IShellFolder_Release(pSF); + } + SHFree(pidl); +} + +void DisplayHelp(HWND hwnd) +{ + SHELL_ErrorBox(hwnd, ERROR_NOT_SUPPORTED); +} diff --git a/sdk/include/reactos/shellutils.h b/sdk/include/reactos/shellutils.h index 756c57c9d73..c45b6ad8770 100644 --- a/sdk/include/reactos/shellutils.h +++ b/sdk/include/reactos/shellutils.h @@ -23,7 +23,7 @@ extern "C" { #endif /* defined(__cplusplus) */ -inline ULONG +static inline ULONG Win32DbgPrint(const char *filename, int line, const char *lpFormat, ...) { char szMsg[512]; @@ -63,11 +63,11 @@ Win32DbgPrint(const char *filename, int line, const char *lpFormat, ...) # define IID_PPV_ARG(Itype, ppType) IID_##Itype, reinterpret_cast<void**>((static_cast<Itype**>(ppType))) # define IID_NULL_PPV_ARG(Itype, ppType) IID_##Itype, NULL, reinterpret_cast<void**>((static_cast<Itype**>(ppType))) #else -# define IID_PPV_ARG(Itype, ppType) IID_##Itype, (void**)(ppType) -# define IID_NULL_PPV_ARG(Itype, ppType) IID_##Itype, NULL, (void**)(ppType) +# define IID_PPV_ARG(Itype, ppType) &IID_##Itype, (void**)(ppType) +# define IID_NULL_PPV_ARG(Itype, ppType) &IID_##Itype, NULL, (void**)(ppType) #endif -inline HRESULT HResultFromWin32(DWORD hr) +static inline HRESULT HResultFromWin32(DWORD hr) { // HRESULT_FROM_WIN32 will evaluate its parameter twice, this function will not. return HRESULT_FROM_WIN32(hr); @@ -75,7 +75,7 @@ inline HRESULT HResultFromWin32(DWORD hr) #if 1 -inline BOOL _ROS_FAILED_HELPER(HRESULT hr, const char* expr, const char* filename, int line) +static inline BOOL _ROS_FAILED_HELPER(HRESULT hr, const char* expr, const char* filename, int line) { if (FAILED(hr)) { @@ -122,6 +122,8 @@ SHELL_ErrorBox(H hwndOwner, UINT Error = GetLastError()) { return SHELL_ErrorBoxHelper(const_cast<HWND>(hwndOwner), Error); } +#else +#define SHELL_ErrorBox SHELL_ErrorBoxHelper #endif #ifdef __cplusplus
2 weeks, 4 days
1
0
0
0
[reactos] 01/01: [SHIMGVW] Choose a better icon image and also support .cur files (#7706)
by Whindmar Saksit
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=329a41458416f633fb6ec…
commit 329a41458416f633fb6ec016dc434b063cd92b9b Author: Whindmar Saksit <whindsaks(a)proton.me> AuthorDate: Wed Feb 12 20:57:51 2025 +0100 Commit: GitHub <noreply(a)github.com> CommitDate: Wed Feb 12 20:57:51 2025 +0100 [SHIMGVW] Choose a better icon image and also support .cur files (#7706) - Choose an icon image based on size and color and place it first so GDI+ will pick it - Change .cur files to .ico so GDI+ can open it CORE-19945 --- dll/win32/shimgvw/CMakeLists.txt | 1 + dll/win32/shimgvw/loader.cpp | 283 +++++++++++++++++++++++++++++++++++++++ dll/win32/shimgvw/shimgvw.c | 81 ++++------- dll/win32/shimgvw/shimgvw.h | 43 ++++++ 4 files changed, 350 insertions(+), 58 deletions(-) diff --git a/dll/win32/shimgvw/CMakeLists.txt b/dll/win32/shimgvw/CMakeLists.txt index 1a4589abd43..15983aff150 100644 --- a/dll/win32/shimgvw/CMakeLists.txt +++ b/dll/win32/shimgvw/CMakeLists.txt @@ -3,6 +3,7 @@ spec2def(shimgvw.dll shimgvw.spec) list(APPEND SOURCE anime.c + loader.cpp shimgvw.c comsup.c shimgvw.rc diff --git a/dll/win32/shimgvw/loader.cpp b/dll/win32/shimgvw/loader.cpp new file mode 100644 index 00000000000..50112f6c486 --- /dev/null +++ b/dll/win32/shimgvw/loader.cpp @@ -0,0 +1,283 @@ +/* + * PROJECT: ReactOS Picture and Fax Viewer + * LICENSE: GPL-2.0 (
https://spdx.org/licenses/GPL-2.0
) + * PURPOSE: Image file browsing and manipulation + * COPYRIGHT: Copyright 2025 Whindmar Saksit <whindsaks(a)proton.me> + */ + +#include <windows.h> +#include <objbase.h> +#include <gdiplus.h> +using namespace Gdiplus; +#include "shimgvw.h" + +#define HResultFromWin32 SHIMGVW_HResultFromWin32 + +static HRESULT Read(HANDLE hFile, void* Buffer, DWORD Size) +{ + DWORD Transferred; + if (!ReadFile(hFile, Buffer, Size, &Transferred, NULL)) + return HResultFromWin32(GetLastError()); + return Size == Transferred ? S_OK : HResultFromWin32(ERROR_HANDLE_EOF); +} + +struct IMAGEINFO +{ + UINT w, h; + BYTE bpp; +}; + +class BitmapInfoHeader : public BITMAPINFOHEADER +{ +public: + BitmapInfoHeader() {} + BitmapInfoHeader(const void* pbmiHeader) { Initialize(pbmiHeader); } + + void Initialize(const void* pbmiHeader) + { + BITMAPINFOHEADER& bih = *(BITMAPINFOHEADER*)pbmiHeader; + if (bih.biSize >= sizeof(BITMAPINFOHEADER)) + { + CopyMemory(this, &bih, min(bih.biSize, sizeof(*this))); + } + else + { + ZeroMemory(this, sizeof(*this)); + BITMAPCOREHEADER& bch = *(BITMAPCOREHEADER*)pbmiHeader; + if (bih.biSize >= sizeof(BITMAPCOREHEADER)) + { + biSize = bch.bcSize; + biWidth = bch.bcWidth; + biHeight = bch.bcHeight; + biPlanes = bch.bcPlanes; + biBitCount = bch.bcBitCount; + biCompression = BI_RGB; + } + } + } +}; + +#include <pshpack1.h> +union PNGSIGNATURE { UINT64 number; BYTE bytes[8]; }; +struct PNGCHUNKHEADER { UINT length, type; }; +struct PNGCHUNKFOOTER { UINT crc; }; +struct PNGIHDR { UINT w, h; BYTE depth, type, compression, filter, interlace; }; +struct PNGSIGANDIHDR +{ + PNGSIGNATURE sig; + PNGCHUNKHEADER chunkheader; + PNGIHDR ihdr; + PNGCHUNKFOOTER chunkfooter; +}; +struct PNGFOOTER { PNGCHUNKHEADER chunkheader; PNGCHUNKFOOTER footer; }; +#include <poppack.h> + +static inline bool IsPngSignature(const void* buffer) +{ + const BYTE* p = (BYTE*)buffer; + return p[0] == 0x89 && p[1] == 'P' && p[2] == 'N' && p[3] == 'G' && + p[4] == 0x0D && p[5] == 0x0A && p[6] == 0x1A && p[7] == 0x0A; +} + +static inline bool IsPngSignature(const void* buffer, SIZE_T size) +{ + return size >= sizeof(PNGSIGNATURE) && IsPngSignature(buffer); +} + +static BYTE GetPngBppFromIHDRData(const void* buffer) +{ + static const BYTE channels[] = { 1, 0, 3, 1, 2, 0, 4 }; + const BYTE* p = (BYTE*)buffer, depth = p[8], type = p[8 + 1]; + return (depth <= 16 && type <= 6) ? channels[type] * depth : 0; +} + +static bool GetInfoFromPng(const void* file, SIZE_T size, IMAGEINFO& info) +{ + C_ASSERT(sizeof(PNGSIGNATURE) == 8); + C_ASSERT(sizeof(PNGSIGANDIHDR) == 8 + (4 + 4 + (4 + 4 + 5) + 4)); + + if (size > sizeof(PNGSIGANDIHDR) + sizeof(PNGFOOTER) && IsPngSignature(file)) + { + const UINT PNGIHDRSIG = 0x52444849; // Note: Big endian + const UINT* chunkhdr = (UINT*)((char*)file + sizeof(PNGSIGNATURE)); + if (BigToHost32(chunkhdr[0]) >= sizeof(PNGIHDR) && chunkhdr[1] == PNGIHDRSIG) + { + info.w = BigToHost32(chunkhdr[2]); + info.h = BigToHost32(chunkhdr[3]); + info.bpp = GetPngBppFromIHDRData(&chunkhdr[2]); + return info.bpp != 0; + } + } + return false; +} + +static bool GetInfoFromBmp(const void* pBitmapInfo, IMAGEINFO& info) +{ + BitmapInfoHeader bih(pBitmapInfo); + info.w = bih.biWidth; + info.h = abs((int)bih.biHeight); + UINT bpp = bih.biBitCount * bih.biPlanes; + info.bpp = LOBYTE(bpp); + return info.w && bpp == info.bpp; +} + +static bool GetInfoFromIcoBmp(const void* pBitmapInfo, IMAGEINFO& stat) +{ + bool ret = GetInfoFromBmp(pBitmapInfo, stat); + stat.h /= 2; // Don't include mask + return ret && stat.h; +} + +EXTERN_C PCWSTR GetExtraExtensionsGdipList(VOID) +{ + return L"*.CUR"; // "*.FOO;*.BAR" etc. +} + +static void OverrideFileContent(HGLOBAL& hMem, DWORD& Size) +{ + PBYTE buffer = (PBYTE)GlobalLock(hMem); + if (!buffer) + return; + + // TODO: We could try to load an ICO/PNG/BMP resource from a PE file here into buffer + + // ICO/CUR + struct ICOHDR { WORD Sig, Type, Count; }; + ICOHDR* pIcoHdr = (ICOHDR*)buffer; + if (Size > sizeof(ICOHDR) && !pIcoHdr->Sig && pIcoHdr->Type > 0 && pIcoHdr->Type < 3 && pIcoHdr->Count) + { + const UINT minbmp = sizeof(BITMAPCOREHEADER) + 1, minpng = sizeof(PNGSIGANDIHDR); + const UINT minfile = min(minbmp, minpng), count = pIcoHdr->Count; + struct ICOENTRY { BYTE w, h, pal, null; WORD planes, bpp; UINT size, offset; }; + ICOENTRY* entries = (ICOENTRY*)&pIcoHdr[1]; + if (Size - sizeof(ICOHDR) > (sizeof(ICOENTRY) + minfile) * count) + { + UINT64 best = 0; + int bestindex = -1; + // Inspect all the images and find the "best" image + for (UINT i = 0; i < count; ++i) + { + BOOL valid = FALSE; + IMAGEINFO info; + const BYTE* data = buffer + entries[i].offset; + if (IsPngSignature(data, entries[i].size)) + valid = GetInfoFromPng(data, entries[i].size, info); + else + valid = GetInfoFromIcoBmp(data, info); + + if (valid) + { + // Note: This treats bpp as more important compared to LookupIconIdFromDirectoryEx + UINT64 score = UINT64(info.w) * info.h * info.bpp; + if (score > best) + { + best = score; + bestindex = i; + } + } + } + if (bestindex >= 0) + { + if (pIcoHdr->Type == 2) + { + // GDI+ does not support .cur files, convert to .ico + pIcoHdr->Type = 1; +#if 0 // Because we are already overriding the order, we don't need to correct the ICOENTRY lookup info + for (UINT i = 0; i < count; ++i) + { + BitmapInfoHeader bih; + const BYTE* data = buffer + entries[i].offset; + if (IsPngSignature(data, entries[i].size)) + { + IMAGEINFO info; + if (!GetInfoFromPng(data, entries[i].size, info)) + continue; + bih.biPlanes = 1; + bih.biBitCount = info.bpp; + entries[i].pal = 0; + } + else + { + bih.Initialize(data); + entries[i].pal = bih.biPlanes * bih.biBitCount <= 8 ? bih.biClrUsed : 0; + } + entries[i].planes = (WORD)bih.biPlanes; + entries[i].bpp = (WORD)bih.biBitCount; + } +#endif + } +#if 0 + // Convert to a .ico with a single image + pIcoHdr->Count = 1; + const BYTE* data = buffer + entries[bestindex].offset; + entries[0] = entries[bestindex]; + entries[0].offset = (UINT)UINT_PTR((PBYTE)&entries[1] - buffer); + MoveMemory(buffer + entries[0].offset, data, entries[0].size); + Size = entries[0].offset + entries[0].size; +#else + // Place the best image first, GDI+ will return the first image + ICOENTRY temp = entries[0]; + entries[0] = entries[bestindex]; + entries[bestindex] = temp; +#endif + } + } + } + + GlobalUnlock(hMem); +} + +static HRESULT LoadImageFromStream(IStream* pStream, GpImage** ppImage) +{ + Status status = DllExports::GdipLoadImageFromStream(pStream, ppImage); + return HResultFromGdiplus(status); +} + +static HRESULT LoadImageFromFileHandle(HANDLE hFile, GpImage** ppImage) +{ + DWORD size = GetFileSize(hFile, NULL); + if (!size || size == INVALID_FILE_SIZE) + return HResultFromWin32(ERROR_NOT_SUPPORTED); + + HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, size); + if (!hMem) + return HResultFromWin32(ERROR_OUTOFMEMORY); + HRESULT hr = E_FAIL; + void* buffer = GlobalLock(hMem); + if (buffer) + { + hr = Read(hFile, buffer, size); + GlobalUnlock(hMem); + if (SUCCEEDED(hr)) + { + OverrideFileContent(hMem, size); + IStream* pStream; + if (SUCCEEDED(hr = CreateStreamOnHGlobal(hMem, TRUE, &pStream))) + { + // CreateStreamOnHGlobal does not know the real size, we do + pStream->SetSize(MakeULargeInteger(size)); + hr = LoadImageFromStream(pStream, ppImage); + pStream->Release(); // Calls GlobalFree + return hr; + } + } + } + GlobalFree(hMem); + return hr; +} + +EXTERN_C HRESULT LoadImageFromPath(LPCWSTR Path, GpImage** ppImage) +{ + // NOTE: GdipLoadImageFromFile locks the file. + // Avoid file locking by using GdipLoadImageFromStream and memory stream. + + HANDLE hFile = CreateFileW(Path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (hFile != INVALID_HANDLE_VALUE) + { + HRESULT hr = LoadImageFromFileHandle(hFile, ppImage); + CloseHandle(hFile); + return hr; + } + return HResultFromWin32(GetLastError()); +} diff --git a/dll/win32/shimgvw/shimgvw.c b/dll/win32/shimgvw/shimgvw.c index c0ce4de2d39..7284266b94a 100644 --- a/dll/win32/shimgvw/shimgvw.c +++ b/dll/win32/shimgvw/shimgvw.c @@ -4,6 +4,7 @@ * PURPOSE: Image file browsing and manipulation * COPYRIGHT: Copyright Dmitry Chapyshev (dmitry(a)reactos.org) * Copyright 2018-2023 Katayama Hirofumi MZ (katayama.hirofumi.mz(a)gmail.com) + * Copyright 2025 Whindmar Saksit <whindsaks(a)proton.me> */ #include "shimgvw.h" @@ -13,6 +14,9 @@ #include <shlobj.h> #include <shellapi.h> +EXTERN_C PCWSTR GetExtraExtensionsGdipList(VOID); +EXTERN_C HRESULT LoadImageFromPath(LPCWSTR Path, GpImage** ppImage); + /* Toolbar image size */ #define TB_IMAGE_WIDTH 16 #define TB_IMAGE_HEIGHT 16 @@ -114,7 +118,6 @@ typedef struct tagPREVIEW_DATA UINT m_nTimerInterval; BOOL m_bHideCursor; POINT m_ptOrigin; - IStream *m_pMemStream; WCHAR m_szFile[MAX_PATH]; } PREVIEW_DATA, *PPREVIEW_DATA; @@ -371,67 +374,20 @@ Preview_pFreeImage(PPREVIEW_DATA pData) g_pImage = NULL; } - if (pData->m_pMemStream) - { - pData->m_pMemStream->lpVtbl->Release(pData->m_pMemStream); - pData->m_pMemStream = NULL; - } - pData->m_szFile[0] = UNICODE_NULL; } -IStream* MemStreamFromFile(LPCWSTR pszFileName) -{ - HANDLE hFile; - DWORD dwFileSize, dwRead; - LPBYTE pbMemFile = NULL; - IStream *pStream; - - hFile = CreateFileW(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, 0, NULL); - if (hFile == INVALID_HANDLE_VALUE) - return NULL; - - dwFileSize = GetFileSize(hFile, NULL); - pbMemFile = QuickAlloc(dwFileSize, FALSE); - if (!dwFileSize || (dwFileSize == INVALID_FILE_SIZE) || !pbMemFile) - { - CloseHandle(hFile); - return NULL; - } - - if (!ReadFile(hFile, pbMemFile, dwFileSize, &dwRead, NULL) || (dwRead != dwFileSize)) - { - QuickFree(pbMemFile); - CloseHandle(hFile); - return NULL; - } - - CloseHandle(hFile); - pStream = SHCreateMemStream(pbMemFile, dwFileSize); - QuickFree(pbMemFile); - return pStream; -} - static VOID Preview_pLoadImage(PPREVIEW_DATA pData, LPCWSTR szOpenFileName) { + HRESULT hr; Preview_pFreeImage(pData); + InvalidateRect(pData->m_hwnd, NULL, FALSE); /* Schedule redraw in case we change to "No preview" */ - pData->m_pMemStream = MemStreamFromFile(szOpenFileName); - if (!pData->m_pMemStream) - { - DPRINT1("MemStreamFromFile() failed\n"); - Preview_UpdateTitle(pData, NULL); - return; - } - - /* NOTE: GdipLoadImageFromFile locks the file. - Avoid file locking by using GdipLoadImageFromStream and memory stream. */ - GdipLoadImageFromStream(pData->m_pMemStream, &g_pImage); - if (!g_pImage) + hr = LoadImageFromPath(szOpenFileName, &g_pImage); + if (FAILED(hr)) { - DPRINT1("GdipLoadImageFromStream() failed\n"); + DPRINT1("GdipLoadImageFromStream() failed, %d\n", hr); Preview_pFreeImage(pData); Preview_UpdateTitle(pData, NULL); return; @@ -439,8 +395,8 @@ Preview_pLoadImage(PPREVIEW_DATA pData, LPCWSTR szOpenFileName) Anime_LoadInfo(&pData->m_Anime); - SHAddToRecentDocs(SHARD_PATHW, szOpenFileName); GetFullPathNameW(szOpenFileName, _countof(pData->m_szFile), pData->m_szFile, NULL); + SHAddToRecentDocs(SHARD_PATHW, pData->m_szFile); /* Reset zoom and redraw display */ Preview_ResetZoom(pData); @@ -625,7 +581,7 @@ static SHIMGVW_FILENODE* pBuildFileList(LPCWSTR szFirstFile) { HANDLE hFindHandle; - WCHAR *extension; + WCHAR *extension, *buffer; WCHAR szSearchPath[MAX_PATH]; WCHAR szSearchMask[MAX_PATH]; WCHAR szFileTypes[MAX_PATH]; @@ -634,15 +590,19 @@ pBuildFileList(LPCWSTR szFirstFile) SHIMGVW_FILENODE *root = NULL; SHIMGVW_FILENODE *conductor = NULL; ImageCodecInfo *codecInfo; - UINT num; - UINT size; + UINT num = 0, size = 0, ExtraSize = 0; UINT j; + const PCWSTR ExtraExtensions = GetExtraExtensionsGdipList(); + const UINT ExtraCount = ExtraExtensions[0] ? 1 : 0; + if (ExtraCount) + ExtraSize += sizeof(*codecInfo) + (wcslen(ExtraExtensions) + 1) * sizeof(WCHAR); + StringCbCopyW(szSearchPath, sizeof(szSearchPath), szFirstFile); PathRemoveFileSpecW(szSearchPath); GdipGetImageDecodersSize(&num, &size); - codecInfo = QuickAlloc(size, FALSE); + codecInfo = QuickAlloc(size + ExtraSize, FALSE); if (!codecInfo) { DPRINT1("QuickAlloc() failed in pLoadFileList()\n"); @@ -650,6 +610,10 @@ pBuildFileList(LPCWSTR szFirstFile) } GdipGetImageDecoders(num, size, codecInfo); + buffer = (PWSTR)((UINT_PTR)codecInfo + size + (sizeof(*codecInfo) * ExtraCount)); + if (ExtraCount) + codecInfo[num].FilenameExtension = wcscpy(buffer, ExtraExtensions); + num += ExtraCount; root = QuickAlloc(sizeof(SHIMGVW_FILENODE), FALSE); if (!root) @@ -663,6 +627,7 @@ pBuildFileList(LPCWSTR szFirstFile) for (j = 0; j < num; ++j) { + // FIXME: Parse each FilenameExtension list to bypass szFileTypes limit StringCbCopyW(szFileTypes, sizeof(szFileTypes), codecInfo[j].FilenameExtension); extension = wcstok(szFileTypes, L";"); diff --git a/dll/win32/shimgvw/shimgvw.h b/dll/win32/shimgvw/shimgvw.h index 776da7f849c..c17a15bb8f2 100644 --- a/dll/win32/shimgvw/shimgvw.h +++ b/dll/win32/shimgvw/shimgvw.h @@ -78,3 +78,46 @@ static inline VOID QuickFree(LPVOID ptr) { HeapFree(GetProcessHeap(), 0, ptr); } + +static inline WORD Swap16(WORD v) +{ + return MAKEWORD(HIBYTE(v), LOBYTE(v)); +} + +static inline UINT Swap32(UINT v) +{ + return MAKELONG(Swap16(HIWORD(v)), Swap16(LOWORD(v))); +} + +#ifdef _WIN32 +#define BigToHost32 Swap32 +#endif + +static inline ULARGE_INTEGER MakeULargeInteger(UINT64 value) +{ + ULARGE_INTEGER ret; + ret.QuadPart = value; + return ret; +} + +static inline HRESULT SHIMGVW_HResultFromWin32(DWORD hr) +{ + // HRESULT_FROM_WIN32 will evaluate its parameter twice, this function will not. + return HRESULT_FROM_WIN32(hr); +} + +static inline HRESULT HResultFromGdiplus(Status status) +{ + switch ((UINT)status) + { + case Ok: return S_OK; + case InvalidParameter: return E_INVALIDARG; + case OutOfMemory: return E_OUTOFMEMORY; + case NotImplemented: return HRESULT_FROM_WIN32(ERROR_CALL_NOT_IMPLEMENTED); + case Win32Error: return SHIMGVW_HResultFromWin32(GetLastError()); + case FileNotFound: return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + case AccessDenied: return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); + case UnknownImageFormat: return HRESULT_FROM_WIN32(ERROR_BAD_FORMAT); + } + return E_FAIL; +}
2 weeks, 5 days
1
0
0
0
[reactos] 08/08: [CRT] Fix cvt to not overflow the buffer on NAN/INF
by Timo Kreuzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=166d83b2065c1b15051a6…
commit 166d83b2065c1b15051a68b8a6092e4d2727f63e Author: Timo Kreuzer <timo.kreuzer(a)reactos.org> AuthorDate: Mon Feb 3 11:06:44 2025 +0200 Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org> CommitDate: Wed Feb 12 16:54:45 2025 +0200 [CRT] Fix cvt to not overflow the buffer on NAN/INF Fixes crash in msvcrt_winetest printf --- sdk/lib/crt/stdlib/fcvtbuf.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sdk/lib/crt/stdlib/fcvtbuf.c b/sdk/lib/crt/stdlib/fcvtbuf.c index a76b27bc515..18966efcb0b 100644 --- a/sdk/lib/crt/stdlib/fcvtbuf.c +++ b/sdk/lib/crt/stdlib/fcvtbuf.c @@ -48,6 +48,21 @@ static char *cvt(double arg, int ndigits, int *decpt, int *sign, char *buf, int double fi, fj; char *p, *p1; + if (_isnan(arg)) + { + snprintf(buf, ndigits, "1.#QNAN"); + *decpt = 0; + *sign = 0; + return buf; + } + if (!_finite(arg)) + { + snprintf(buf, ndigits, "1.#INF"); + *decpt = 0; + *sign = 0; + return buf; + } + if (ndigits >= CVTBUFSIZE - 1) ndigits = CVTBUFSIZE - 2; r2 = 0; *sign = 0;
2 weeks, 5 days
1
0
0
0
[reactos] 07/08: [MSVCRT_WINETEST] Add checks to not crash on reactos
by Timo Kreuzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4a63e19e47ef12ea630ec…
commit 4a63e19e47ef12ea630ec69205f9b303b0df14e3 Author: Timo Kreuzer <timo.kreuzer(a)reactos.org> AuthorDate: Mon Feb 3 11:08:26 2025 +0200 Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org> CommitDate: Wed Feb 12 16:54:45 2025 +0200 [MSVCRT_WINETEST] Add checks to not crash on reactos --- modules/rostests/winetests/msvcrt/locale.c | 6 ++++++ modules/rostests/winetests/msvcrt/misc.c | 8 ++++++++ modules/rostests/winetests/msvcrt/string.c | 8 ++++++++ 3 files changed, 22 insertions(+) diff --git a/modules/rostests/winetests/msvcrt/locale.c b/modules/rostests/winetests/msvcrt/locale.c index 62632ce4b9d..a9ade6f5c41 100644 --- a/modules/rostests/winetests/msvcrt/locale.c +++ b/modules/rostests/winetests/msvcrt/locale.c @@ -627,6 +627,9 @@ static void test_setlocale(void) if(IsValidCodePage(atoi(buf))) { ret = setlocale(LC_ALL, ".OCP"); ok(ret != NULL, "ret == NULL\n"); +#ifdef __REACTOS__ + if (ret == NULL) ptr = NULL; else +#endif ptr = strchr(ret, '.'); ok(ptr && !strcmp(ptr + 1, buf), "ret %s, buf %s.\n", ret, buf); } @@ -636,6 +639,9 @@ static void test_setlocale(void) len = sprintf(buf, "%d", GetACP()); ret = setlocale(LC_ALL, ".ACP"); ok(ret != NULL, "ret == NULL\n"); +#ifdef __REACTOS__ + if (ret == NULL) ptr = NULL; else +#endif ptr = strchr(ret, '.'); ok(ptr && !strncmp(ptr + 1, buf, len), "ret %s, buf %s.\n", ret, buf); diff --git a/modules/rostests/winetests/msvcrt/misc.c b/modules/rostests/winetests/msvcrt/misc.c index 7b54b3aeb88..cb7dc24e18c 100644 --- a/modules/rostests/winetests/msvcrt/misc.c +++ b/modules/rostests/winetests/msvcrt/misc.c @@ -25,6 +25,7 @@ #include <stdio.h> #include <math.h> #include <process.h> +#include <versionhelpers.h> static inline BOOL almost_equal(double d1, double d2) { if(d1-d2>-1e-30 && d1-d2<1e-30) @@ -393,6 +394,13 @@ static void test__popen(const char *name) ret = fputs("child-to-parent\n", pipe); ok(ret != EOF, "fputs returned %x\n", ret); +#ifdef __REACTOS__ + if (IsReactOS()) + { + skip("Skipping _pclose, because it hangs on reactos\n"); + return; + } +#endif ret = _pclose(pipe); ok(ret == 0x3, "_pclose returned %x, expected 0x3\n", ret); } diff --git a/modules/rostests/winetests/msvcrt/string.c b/modules/rostests/winetests/msvcrt/string.c index b6115c08bd1..f88d672d573 100644 --- a/modules/rostests/winetests/msvcrt/string.c +++ b/modules/rostests/winetests/msvcrt/string.c @@ -37,6 +37,7 @@ #include "winbase.h" #include "winnls.h" #include "winuser.h" +#include <versionhelpers.h> static char *buf_to_string(const unsigned char *bin, int len, int nr) { @@ -2117,6 +2118,13 @@ static void test__strtod(void) for (i=0; i<ARRAY_SIZE(tests); i++) { +#ifdef __REACTOS__ + if ((i == 19) && IsReactOS()) + { + skip("Skipping i == 19, because it crashes on ReactOS\n"); + continue; + } +#endif errno = 0xdeadbeef; d = strtod(tests[i].str, &end); ok(d == tests[i].ret, "%d) d = %.16e\n", i, d);
2 weeks, 5 days
1
0
0
0
[reactos] 06/08: [MSVCRT_WINETEST] Fixes for windows 2003
by Timo Kreuzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=748fdbcd6afc7bfedb161…
commit 748fdbcd6afc7bfedb16171a5fd0973fb89eb71e Author: Timo Kreuzer <timo.kreuzer(a)reactos.org> AuthorDate: Thu Jan 30 15:30:55 2025 +0200 Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org> CommitDate: Wed Feb 12 16:54:45 2025 +0200 [MSVCRT_WINETEST] Fixes for windows 2003 --- modules/rostests/winetests/msvcrt/cpp.c | 5 +++++ modules/rostests/winetests/msvcrt/environ.c | 6 +++--- modules/rostests/winetests/msvcrt/file.c | 6 ++++-- modules/rostests/winetests/msvcrt/printf.c | 10 ++++++++++ modules/rostests/winetests/msvcrt/signal.c | 4 ++-- modules/rostests/winetests/msvcrt/string.c | 27 +++++++++++++++++++++------ sdk/include/reactos/wine/test.h | 3 +++ 7 files changed, 48 insertions(+), 13 deletions(-) diff --git a/modules/rostests/winetests/msvcrt/cpp.c b/modules/rostests/winetests/msvcrt/cpp.c index bfc092e0591..2bbf34dcd01 100644 --- a/modules/rostests/winetests/msvcrt/cpp.c +++ b/modules/rostests/winetests/msvcrt/cpp.c @@ -1338,6 +1338,11 @@ static void test_demangle(void) for (i = 0; i < ARRAY_SIZE(test); i++) { + if (((i == 149) || (i == 150)) && (_winver < 0x600)) + { + skip("Skipping test with i = %u, because it fails on Windows 2003\n", i); + continue; + } name = p__unDName(0, test[i].in, 0, malloc, free, test[i].flags); ok(name != NULL, "%u: unDName failed\n", i); if (!name) continue; diff --git a/modules/rostests/winetests/msvcrt/environ.c b/modules/rostests/winetests/msvcrt/environ.c index 9951c5b1308..4b6f5bc22b4 100644 --- a/modules/rostests/winetests/msvcrt/environ.c +++ b/modules/rostests/winetests/msvcrt/environ.c @@ -233,12 +233,12 @@ static void test__wenviron(void) wchar_t ***retptr = p__p___winitenv(); wchar_t *value; - ok( *retptr != NULL, "Expected *__p___winitenv() to be NULL\n" ); + skip_2k3_fail ok( *retptr != NULL, "Expected *__p___winitenv() to be NULL\n" ); ok( *retptr != *p_wenviron, "Expected _wenviron to be different from __p___winitenv() %p %p\n", *retptr, *p_wenviron ); /* test that w-initial env is derived from current _environ[] and not from ansi initial env */ value = env_get_valueW( *retptr, L"cat" ); - ok( value && !wcscmp( value, L"dog" ), + skip_2k3_fail ok( value && !wcscmp( value, L"dog" ), "Expecting initial env to be derived from current env (got %ls)\n", value ); } _putenv("cat="); @@ -461,7 +461,7 @@ START_TEST(environ) { ok( getenv( "__winetest_dog" ) && !strcmp( getenv( "__winetest_dog" ), "bark" ), "Couldn't find env var\n" ); - ok( _wgetenv( L"__winetest_\u263a" ) && !wcscmp( _wgetenv( L"__winetest_\u263a" ), L"\u03b2" ), + skip_2k3_fail ok( _wgetenv( L"__winetest_\u263a" ) && !wcscmp( _wgetenv( L"__winetest_\u263a" ), L"\u03b2" ), "Couldn't find unicode env var\n" ); return; } diff --git a/modules/rostests/winetests/msvcrt/file.c b/modules/rostests/winetests/msvcrt/file.c index d082bb269c6..ac02ed58859 100644 --- a/modules/rostests/winetests/msvcrt/file.c +++ b/modules/rostests/winetests/msvcrt/file.c @@ -2099,9 +2099,11 @@ static void test_fopen_fclose_fcloseall( void ) ret = fclose(stream3); ok(ret == EOF, "Closing file '%s' returned %d\n", fname3, ret); ok(errno == 0xdeadbeef, "errno = %d\n", errno); + skip_2k3_crash { ret = fclose(NULL); ok(ret == EOF, "Closing NULL file returned %d\n", ret); ok(errno == EINVAL, "errno = %d\n", errno); + } /* testing fcloseall() */ numclosed = _fcloseall(); @@ -3051,13 +3053,13 @@ static void test_ioinfo_flags(void) info = &__pioinfo[tempfd / MSVCRT_FD_BLOCK_SIZE][tempfd % MSVCRT_FD_BLOCK_SIZE]; ok(!!info, "NULL info.\n"); ok(info->handle == handle, "Unexpected handle %p, expected %p.\n", info->handle, handle); - ok(info->exflag == (EF_UTF16 | EF_CRIT_INIT | EF_UNK_UNICODE), "Unexpected exflag %#x.\n", info->exflag); + skip_2k3_fail ok(info->exflag == (EF_UTF16 | EF_CRIT_INIT | EF_UNK_UNICODE), "Unexpected exflag %#x.\n", info->exflag); ok(info->wxflag == (WX_TEXT | WX_OPEN), "Unexpected wxflag %#x.\n", info->wxflag); close(tempfd); ok(info->handle == INVALID_HANDLE_VALUE, "Unexpected handle %p.\n", info->handle); - ok(info->exflag == (EF_UTF16 | EF_CRIT_INIT | EF_UNK_UNICODE), "Unexpected exflag %#x.\n", info->exflag); + skip_2k3_fail ok(info->exflag == (EF_UTF16 | EF_CRIT_INIT | EF_UNK_UNICODE), "Unexpected exflag %#x.\n", info->exflag); ok(!info->wxflag, "Unexpected wxflag %#x.\n", info->wxflag); info = &__pioinfo[(tempfd + 4) / MSVCRT_FD_BLOCK_SIZE][(tempfd + 4) % MSVCRT_FD_BLOCK_SIZE]; diff --git a/modules/rostests/winetests/msvcrt/printf.c b/modules/rostests/winetests/msvcrt/printf.c index dc0038b3372..ec314544c98 100644 --- a/modules/rostests/winetests/msvcrt/printf.c +++ b/modules/rostests/winetests/msvcrt/printf.c @@ -723,6 +723,11 @@ static void test_xcvt(void) ok( decpt == test_cvt_testcases[i].expdecpt_e, "%d) _ecvt() decimal point wrong, got %d expected %d\n", i, decpt, test_cvt_testcases[i].expdecpt_e); + if (((i == 10) || (i == 11) || (i == 12)) && (_winver < 0x600)) + { + skip("broken on win 2003\n"); + continue; + } ok( sign == test_cvt_testcases[i].expsign, "%d) _ecvt() sign wrong, got %d expected %d\n", i, sign, test_cvt_testcases[i].expsign); @@ -739,6 +744,11 @@ static void test_xcvt(void) ok( decpt == test_cvt_testcases[i].expdecpt_f, "%d) _fcvt() decimal point wrong, got %d expected %d\n", i, decpt, test_cvt_testcases[i].expdecpt_f); + if (((i == 10) || (i == 11) || (i == 12)) && (_winver < 0x600)) + { + skip("broken on win 2003\n"); + continue; + } ok( sign == test_cvt_testcases[i].expsign, "%d) _fcvt() sign wrong, got %d expected %d\n", i, sign, test_cvt_testcases[i].expsign); diff --git a/modules/rostests/winetests/msvcrt/signal.c b/modules/rostests/winetests/msvcrt/signal.c index ad6ea6ecf90..b78aca510c0 100644 --- a/modules/rostests/winetests/msvcrt/signal.c +++ b/modules/rostests/winetests/msvcrt/signal.c @@ -67,10 +67,10 @@ static void test___pxcptinfoptrs(void) signal(SIGABRT, sighandler); res = raise(SIGABRT); - ok(res == 0, "failed to raise SIGBREAK\n"); + skip_2k3_fail ok(res == 0, "failed to raise SIGBREAK\n"); ok(*ret == (void*)0xdeadbeef, "*ret = %p\n", *ret); - ok(test_value == 2, "test_value = %d\n", test_value); + skip_2k3_fail ok(test_value == 2, "test_value = %d\n", test_value); } START_TEST(signal) diff --git a/modules/rostests/winetests/msvcrt/string.c b/modules/rostests/winetests/msvcrt/string.c index 911a06e47d4..b6115c08bd1 100644 --- a/modules/rostests/winetests/msvcrt/string.c +++ b/modules/rostests/winetests/msvcrt/string.c @@ -338,7 +338,7 @@ static void test_mbcp(void) expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[5]), FALSE, int, "%d"); /* _mbsbtype */ - expect_eq(_mbsbtype(NULL, 0), _MBC_ILLEGAL, int, "%d"); + skip_2k3_crash expect_eq(_mbsbtype(NULL, 0), _MBC_ILLEGAL, int, "%d"); expect_eq(_mbsbtype(mbstring, 0), _MBC_LEAD, int, "%d"); expect_eq(_mbsbtype(mbstring, 1), _MBC_TRAIL, int, "%d"); expect_eq(_mbsbtype(mbstring, 2), _MBC_LEAD, int, "%d"); @@ -465,6 +465,7 @@ static void test_mbcp(void) expect_bin(buf, "\x00\xff", 2); } + skip_2k3_crash { errno = 0xdeadbeef; ret = _mbsncpy(NULL, mbstring, 1); ok(ret == NULL, "_mbsncpy returned %p, expected NULL\n", ret); @@ -476,6 +477,7 @@ static void test_mbcp(void) ok(ret == NULL, "_mbsncpy returned %p, expected NULL\n", ret); ok(errno == EINVAL, "_mbsncpy returned %d\n", errno); expect_bin(buf, "\xff\xff\xff", 3); + } errno = 0xdeadbeef; ret = _mbsncpy(NULL, mbstring, 0); @@ -488,6 +490,7 @@ static void test_mbcp(void) ok(ret == buf, "_mbsncpy returned %p, expected %sp\n", ret, buf); ok(errno == 0xdeadbeef, "_mbsncpy should not change errno\n"); + skip_2k3_crash { memset(buf, 0xff, sizeof(buf)); errno = 0xdeadbeef; ret = _mbsncpy(NULL, mbstring, 1); @@ -499,6 +502,7 @@ static void test_mbcp(void) ret = _mbsncpy(buf, NULL, 1); ok(ret == NULL, "_mbsncpy returned %p, expected NULL\n", ret); ok(errno == EINVAL, "_mbsncpy returned %d\n", errno); + } memset(buf, 0xff, sizeof(buf)); ret = _mbsncpy(NULL, mbstring, 0); @@ -724,6 +728,7 @@ static void test_strcmp(void) ret = p_strncmp( "abc", "abcd", 3 ); ok( ret == 0, "wrong ret %d\n", ret ); + skip_2k3_fail { #ifdef _WIN64 ret = p_strncmp( "", "abc", 3 ); ok( ret == -1, "wrong ret %d\n", ret ); @@ -739,6 +744,7 @@ static void test_strcmp(void) ret = p_strncmp( "ab\xb0", "ab\xa0", 3 ); ok( ret == 0xb0 - 0xa0, "wrong ret %d\n", ret ); #endif + } ret = p_strncmp( "ab\xb0", "ab\xa0", 2 ); ok( ret == 0, "wrong ret %d\n", ret ); ret = p_strncmp( "ab\xc2", "ab\xc2", 3 ); @@ -3389,6 +3395,7 @@ static void test_tolower(void) ret = p_tolower((unsigned char)0xD0); ok(ret == 0xF0, "ret = %x\n", ret); + skip_2k3_fail { ok(setlocale(LC_ALL, "Japanese_Japan.932") != NULL, "setlocale failed.\n"); errno = 0xdeadbeef; ret = p_tolower((signed char)0xd0); @@ -3428,6 +3435,7 @@ static void test_tolower(void) ret = p_tolower(0xd0); ok(ret == 0xd0, "Got %#x.\n", ret); ok(errno == 0xdeadbeef, "Got errno %d.\n", errno); + } setlocale(LC_ALL, "C"); } @@ -3578,7 +3586,7 @@ static void test__stricmp(void) ret = _stricmp("abc\xa5\xa1", "abc"); ok(ret > 0, "_stricmp returned %d\n", ret); - ok(setlocale(LC_ALL, "Japanese_Japan.932") != NULL, "setlocale failed.\n"); + skip_2k3_fail ok(setlocale(LC_ALL, "Japanese_Japan.932") != NULL, "setlocale failed.\n"); ret = _stricmp("test", "test"); ok(ret == 0, "_stricmp returned %d\n", ret); ret = _stricmp("a", "z"); @@ -3647,6 +3655,11 @@ static void test__wcstoi64(void) for (i = 0; i < ARRAY_SIZE(tests); i++) { + if ((i == 20) && (_winver < 0x600)) + { + skip("Skipping test with i = 20, because it fails on Windows 2003\n"); + continue; + } res = p_wcstoi64( tests[i].str, &endpos, tests[i].base ); ok( res == tests[i].res, "%u: %s res %s\n", i, wine_dbgstr_w(tests[i].str), wine_dbgstr_longlong(res) ); @@ -4867,7 +4880,7 @@ static void test_mbsrev(void) strcpy((char *)buf, "\x36\x8c"); ret = _mbsrev(buf); ok(ret == buf, "ret = %p, expected %p\n", ret, buf); - ok(!memcmp(buf, "\x36", 2), "buf = %s\n", wine_dbgstr_a((char *)buf)); + skip_2k3_fail ok(!memcmp(buf, "\x36", 2), "buf = %s\n", wine_dbgstr_a((char *)buf)); _setmbcp(cp); } @@ -4985,7 +4998,7 @@ static void test_toupper(void) errno = 0xdeadbeef; ret = p_toupper((signed char)0xf0); ok(ret == 0xd0, "Got %#x.\n", ret); - ok(errno == EILSEQ, "Got errno %d.\n", errno); + skip_2k3_fail ok(errno == EILSEQ, "Got errno %d.\n", errno); errno = 0xdeadbeef; ret = p_toupper(0xf0); ok(ret == 0xd0, "Got %#x.\n", ret); @@ -4995,12 +5008,13 @@ static void test_toupper(void) errno = 0xdeadbeef; ret = p_toupper((signed char)0xa5); ok(ret == 0xa5, "Got %#x.\n", ret); - ok(errno == EILSEQ, "Got errno %d.\n", errno); + skip_2k3_fail ok(errno == EILSEQ, "Got errno %d.\n", errno); errno = 0xdeadbeef; ret = p_toupper((signed char)0xb9); ok(ret == 0xa5, "Got %#x.\n", ret); - ok(errno == EILSEQ, "Got errno %d.\n", errno); + skip_2k3_fail ok(errno == EILSEQ, "Got errno %d.\n", errno); + skip_2k3_fail { ok(setlocale(LC_ALL, "Japanese_Japan.932") != NULL, "setlocale failed.\n"); errno = 0xdeadbeef; ret = p_toupper((signed char)0xf0); @@ -5020,6 +5034,7 @@ static void test_toupper(void) ret = p_toupper(0xf0); ok(ret == 0xf0, "Got %#x.\n", ret); ok(errno == 0xdeadbeef, "Got errno %d.\n", errno); + } setlocale(LC_ALL, "C"); } diff --git a/sdk/include/reactos/wine/test.h b/sdk/include/reactos/wine/test.h index 35c2214e354..7dbd2845f99 100644 --- a/sdk/include/reactos/wine/test.h +++ b/sdk/include/reactos/wine/test.h @@ -187,6 +187,9 @@ extern void winetest_pop_context(void); winetest_loop_nocount(); \ winetest_end_nocount()) +#define skip_2k3_crash if (_winver < 0x600) skip("Test skipped, because it crashes on win 2003\n"); else +#define skip_2k3_fail if (_winver < 0x600) skip("Test skipped, because it fails on win 2003\n"); else + #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #ifdef NONAMELESSUNION
2 weeks, 5 days
1
0
0
0
[reactos] 05/08: [MSVCRT_WINETEST] Sync to wine-10.0
by Timo Kreuzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=063c818c729bd2eeb560c…
commit 063c818c729bd2eeb560c691fdbf1297c94a4d24 Author: Timo Kreuzer <timo.kreuzer(a)reactos.org> AuthorDate: Thu Jan 30 12:42:59 2025 +0200 Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org> CommitDate: Wed Feb 12 16:54:45 2025 +0200 [MSVCRT_WINETEST] Sync to wine-10.0 --- modules/rostests/winetests/msvcrt/CMakeLists.txt | 17 +- modules/rostests/winetests/msvcrt/cpp.c | 279 ++-- modules/rostests/winetests/msvcrt/data.c | 22 +- modules/rostests/winetests/msvcrt/dir.c | 118 +- modules/rostests/winetests/msvcrt/environ.c | 386 ++++-- modules/rostests/winetests/msvcrt/file.c | 694 +++++++++- modules/rostests/winetests/msvcrt/heap.c | 103 +- modules/rostests/winetests/msvcrt/locale.c | 227 ++- modules/rostests/winetests/msvcrt/misc.c | 151 +- modules/rostests/winetests/msvcrt/printf.c | 1191 ++++++---------- modules/rostests/winetests/msvcrt/scanf.c | 111 +- modules/rostests/winetests/msvcrt/string.c | 1599 +++++++++++++++++++--- modules/rostests/winetests/msvcrt/time.c | 455 +++--- 13 files changed, 3694 insertions(+), 1659 deletions(-) diff --git a/modules/rostests/winetests/msvcrt/CMakeLists.txt b/modules/rostests/winetests/msvcrt/CMakeLists.txt index 53cb3a0067c..8ee88854dc9 100644 --- a/modules/rostests/winetests/msvcrt/CMakeLists.txt +++ b/modules/rostests/winetests/msvcrt/CMakeLists.txt @@ -1,4 +1,6 @@ +remove_definitions(-D_CRT_NON_CONFORMING_SWPRINTFS) + list(APPEND SOURCE cpp.c data.c @@ -15,7 +17,7 @@ list(APPEND SOURCE time.c) list(APPEND PCH_SKIP_SOURCE - printf.c # _CRT_NON_CONFORMING_SWPRINTFS + printf.c testlist.c) add_executable(msvcrt_winetest @@ -25,6 +27,8 @@ add_executable(msvcrt_winetest target_compile_definitions(msvcrt_winetest PRIVATE WINETEST_USE_DBGSTR_LONGLONG _CRT_NONSTDC_NO_DEPRECATE + _USE_MATH_DEFINES + WIN32_NO_STATUS= __msvcrt_ulong=ULONG) if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") @@ -34,13 +38,14 @@ if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") endif() endif() -set_module_type(msvcrt_winetest win32cui) -add_importlibs(msvcrt_winetest advapi32 msvcrt kernel32) -target_link_libraries(msvcrt_winetest oldnames) - if(MSVC) - add_importlibs(msvcrt_winetest ntdll) + # 'swscanf' : unknown type field character '\xe1' in format specifier + target_compile_options(msvcrt_winetest PRIVATE /wd4476) endif() +set_module_type(msvcrt_winetest win32cui) +add_importlibs(msvcrt_winetest advapi32 msvcrt kernel32 ntdll) +target_link_libraries(msvcrt_winetest oldnames) + add_pch(msvcrt_winetest precomp.h "${PCH_SKIP_SOURCE}") add_rostests_file(TARGET msvcrt_winetest) diff --git a/modules/rostests/winetests/msvcrt/cpp.c b/modules/rostests/winetests/msvcrt/cpp.c index 07b49ae755d..bfc092e0591 100644 --- a/modules/rostests/winetests/msvcrt/cpp.c +++ b/modules/rostests/winetests/msvcrt/cpp.c @@ -44,12 +44,8 @@ typedef struct __type_info #endif /* Function pointers. We need to use these to call these funcs as __thiscall */ -static HMODULE hMsvcrt; - -static void* (__cdecl *poperator_new)(unsigned int); +static void* (__cdecl *poperator_new)(size_t); static void (__cdecl *poperator_delete)(void*); -static void* (__cdecl *pmalloc)(unsigned int); -static void (__cdecl *pfree)(void*); /* exception */ static void (__thiscall *pexception_ctor)(exception*,LPCSTR*); @@ -112,9 +108,6 @@ static void* (__cdecl *p__RTDynamicCast)(void*,int,void*,void*,int); static char* (__cdecl *p__unDName)(char*,const char*,int,void*,void*,unsigned short int); -/* _very_ early native versions have serious RTTI bugs, so we check */ -static void* bAncientVersion; - /* Emulate a __thiscall */ #ifdef __i386__ @@ -157,23 +150,12 @@ static void init_thiscall_thunk(void) #endif /* __i386__ */ /* Some exports are only available in later versions */ -#define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y) +#define SETNOFAIL(x,y) x = (void*)GetProcAddress(hmsvcrt,y) #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0) static BOOL InitFunctionPtrs(void) { - hMsvcrt = GetModuleHandleA("msvcrt.dll"); - if (!hMsvcrt) - hMsvcrt = GetModuleHandleA("msvcrtd.dll"); - ok(hMsvcrt != 0, "GetModuleHandleA failed\n"); - if (!hMsvcrt) - { - win_skip("Could not load msvcrt.dll\n"); - return FALSE; - } - - SET(pmalloc, "malloc"); - SET(pfree, "free"); + HMODULE hmsvcrt = GetModuleHandleA("msvcrt.dll"); SET(pexception_vtable, "??_7exception@@6B@"); SET(pbad_typeid_vtable, "??_7bad_typeid@@6B@"); @@ -187,7 +169,6 @@ static BOOL InitFunctionPtrs(void) SET(p__unDName,"__unDName"); /* Extremely early versions export logic_error, and crash in RTTI */ - SETNOFAIL(bAncientVersion, "??0logic_error@@QAE@ABQBD@Z"); if (sizeof(void *) > sizeof(int)) /* 64-bit initialization */ { SETNOFAIL(poperator_new, "??_U@YAPEAX_K@Z"); @@ -242,50 +223,50 @@ static BOOL InitFunctionPtrs(void) SETNOFAIL(poperator_new, "??_U@YAPAXI@Z"); SETNOFAIL(poperator_delete, "??_V@YAXPAX@Z"); - SET(pexception_ctor, "??0exception@std@@QAA@ABQBD@Z"); - SET(pexception_copy_ctor, "??0exception@std@@QAA@ABV01@@Z"); - SET(pexception_default_ctor, "??0exception@std@@QAA@XZ"); - SET(pexception_dtor, "??1exception@std@@UAA@XZ"); - SET(pexception_opequals, "??4exception@std@@QAAAAV01@ABV01@@Z"); - SET(pexception_what, "?what@exception@std@@UBAPBDXZ"); - SET(pexception_vector_dtor, "??_Eexception@@UAEPAXI@Z");/**/ - SET(pexception_scalar_dtor, "??_Gexception@@UAEPAXI@Z");/**/ - - SET(pbad_typeid_ctor, "??0bad_typeid@std@@QAA@PBD@Z"); - SETNOFAIL(pbad_typeid_ctor_closure, "??_Fbad_typeid@std@@QAAXXZ"); - SET(pbad_typeid_copy_ctor, "??0bad_typeid@std@@QAA@ABV01@@Z"); - SET(pbad_typeid_dtor, "??1bad_typeid@std@@UAA@XZ"); - SET(pbad_typeid_opequals, "??4bad_typeid@std@@QAAAAV01@ABV01@@Z"); - SET(pbad_typeid_what, "?what@exception@std@@UBAPBDXZ"); - SET(pbad_typeid_vector_dtor, "??_Ebad_cast@@UAEPAXI@Z"); - SET(pbad_typeid_scalar_dtor, "??_Gbad_cast@@UAEPAXI@Z"); + SET(pexception_ctor, "??0exception@@QAA@ABQBD@Z"); + SET(pexception_copy_ctor, "??0exception@@QAA@ABV0@@Z"); + SET(pexception_default_ctor, "??0exception@@QAA@XZ"); + SET(pexception_dtor, "??1exception@@UAA@XZ"); + SET(pexception_opequals, "??4exception@@QAAAAV0@ABV0@@Z"); + SET(pexception_what, "?what@exception@@UBAPBDXZ"); + pexception_vector_dtor = (void*)pexception_vtable[0]; + pexception_scalar_dtor = (void*)pexception_vtable[0]; + + SET(pbad_typeid_ctor, "??0bad_typeid@@QAA@PBD@Z"); + SETNOFAIL(pbad_typeid_ctor_closure, "??_Fbad_typeid@@QAAXXZ"); + SET(pbad_typeid_copy_ctor, "??0bad_typeid@@QAA@ABV0@@Z"); + SET(pbad_typeid_dtor, "??1bad_typeid@@UAA@XZ"); + SET(pbad_typeid_opequals, "??4bad_typeid@@QAAAAV0@ABV0@@Z"); + SET(pbad_typeid_what, "?what@exception@@UBAPBDXZ"); + pbad_typeid_vector_dtor = (void*)pbad_typeid_vtable[0]; + pbad_typeid_scalar_dtor = (void*)pbad_typeid_vtable[0]; SETNOFAIL(pbad_cast_ctor, "??0bad_cast@@QAE@ABQBD@Z"); if (!pbad_cast_ctor) - SET(pbad_cast_ctor, "??0bad_cast@std@@AAA@PBQBD@Z"); - SETNOFAIL(pbad_cast_ctor2, "??0bad_cast@std@@QAA@PBD@Z"); - SETNOFAIL(pbad_cast_ctor_closure, "??_Fbad_cast@std@@QAAXXZ"); - /* FIXME: No ARM equivalent for "??0bad_cast@@QAE@ABV0@@Z" */ - SET(pbad_cast_dtor, "??1bad_cast@std@@UAA@XZ"); - SET(pbad_cast_opequals, "??4bad_cast@std@@QAAAAV01@ABV01@@Z"); - SET(pbad_cast_what, "?what@exception@std@@UBAPBDXZ"); - SET(pbad_cast_vector_dtor, "??_Ebad_cast@@UAEPAXI@Z"); - SET(pbad_cast_scalar_dtor, "??_Gbad_cast@@UAEPAXI@Z"); + SET(pbad_cast_ctor, "??0bad_cast@@AAA@PBQBD@Z"); + SETNOFAIL(pbad_cast_ctor2, "??0bad_cast@@QAA@PBD@Z"); + SETNOFAIL(pbad_cast_ctor_closure, "??_Fbad_cast@@QAAXXZ"); + SET(pbad_cast_copy_ctor, "??0bad_cast@@QAA@ABV0@@Z"); + SET(pbad_cast_dtor, "??1bad_cast@@UAA@XZ"); + SET(pbad_cast_opequals, "??4bad_cast@@QAAAAV0@ABV0@@Z"); + SET(pbad_cast_what, "?what@exception@@UBAPBDXZ"); + pbad_cast_vector_dtor = (void*)pbad_cast_vtable[0]; + pbad_cast_scalar_dtor = (void*)pbad_cast_vtable[0]; - SET(p__non_rtti_object_ctor, "??0__non_rtti_object@std@@QAA@PBD@Z"); - SET(p__non_rtti_object_copy_ctor, "??0__non_rtti_object@std@@QAA@ABV01@@Z"); - SET(p__non_rtti_object_dtor, "??1__non_rtti_object@std@@UAA@XZ"); - SET(p__non_rtti_object_opequals, "??4__non_rtti_object@std@@QAAAAV01@ABV01@@Z"); - SET(p__non_rtti_object_what, "?what@exception@std@@UBAPBDXZ"); - SET(p__non_rtti_object_vector_dtor, "??_E__non_rtti_object@@UAEPAXI@Z"); - SET(p__non_rtti_object_scalar_dtor, "??_G__non_rtti_object@@UAEPAXI@Z"); + SET(p__non_rtti_object_ctor, "??0__non_rtti_object@@QAA@PBD@Z"); + SET(p__non_rtti_object_copy_ctor, "??0__non_rtti_object@@QAA@ABV0@@Z"); + SET(p__non_rtti_object_dtor, "??1__non_rtti_object@@UAA@XZ"); + SET(p__non_rtti_object_opequals, "??4__non_rtti_object@@QAAAAV0@ABV0@@Z"); + SET(p__non_rtti_object_what, "?what@exception@@UBAPBDXZ"); + p__non_rtti_object_vector_dtor = (void*)p__non_rtti_object_vtable[0]; + p__non_rtti_object_scalar_dtor = (void*)p__non_rtti_object_vtable[0]; SET(ptype_info_dtor, "??1type_info@@UAA@XZ"); SET(ptype_info_raw_name, "?raw_name@type_info@@QBAPBDXZ"); - SET(ptype_info_name, "?name@type_info@@QBEPBDXZ"); - SET(ptype_info_before, "?before@type_info@@QBA_NABV1@@Z"); - SET(ptype_info_opequals_equals, "??8type_info@@QBA_NABV0@@Z"); - SET(ptype_info_opnot_equals, "??9type_info@@QBA_NABV0@@Z"); + SET(ptype_info_name, "?name@type_info@@QBAPBDXZ"); + SET(ptype_info_before, "?before@type_info@@QBAHABV1@@Z"); + SET(ptype_info_opequals_equals, "??8type_info@@QBAHABV0@@Z"); + SET(ptype_info_opnot_equals, "??9type_info@@QBAHABV0@@Z"); #else SETNOFAIL(poperator_new, "??_U@YAPAXI@Z"); SETNOFAIL(poperator_delete, "??_V@YAXPAX@Z"); @@ -338,9 +319,9 @@ static BOOL InitFunctionPtrs(void) } if (!poperator_new) - poperator_new = pmalloc; + poperator_new = malloc; if (!poperator_delete) - poperator_delete = pfree; + poperator_delete = free; init_thiscall_thunk(); return TRUE; @@ -448,7 +429,7 @@ static void test_exception(void) name = call_func1(pexception_what, &e); ok(e.name == name, "Bad exception name from vtable e::what()\n"); - if (p__RTtypeid && !bAncientVersion) + if (p__RTtypeid) { /* Check the rtti */ type_info *ti = p__RTtypeid(&e); @@ -571,7 +552,7 @@ static void test_bad_typeid(void) name = call_func1(pbad_typeid_what, &e); ok(e.name == name, "Bad bad_typeid name from vtable e::what()\n"); - if (p__RTtypeid && !bAncientVersion) + if (p__RTtypeid) { /* Check the rtti */ type_info *ti = p__RTtypeid(&e); @@ -699,7 +680,7 @@ static void test_bad_cast(void) name = call_func1(pbad_cast_what, &e); ok(e.name == name, "Bad bad_cast name from vtable e::what()\n"); - if (p__RTtypeid && !bAncientVersion) + if (p__RTtypeid) { /* Check the rtti */ type_info *ti = p__RTtypeid(&e); @@ -801,7 +782,7 @@ static void test___non_rtti_object(void) name = call_func1(p__non_rtti_object_what, &e); ok(e.name == name, "Bad __non_rtti_object name from vtable e::what()\n"); - if (p__RTtypeid && !bAncientVersion) + if (p__RTtypeid) { /* Check the rtti */ type_info *ti = p__RTtypeid(&e); @@ -818,14 +799,14 @@ static void test_type_info(void) char* name; int res; - if (!pmalloc || !pfree || !ptype_info_dtor || !ptype_info_raw_name || + if (!ptype_info_dtor || !ptype_info_raw_name || !ptype_info_name || !ptype_info_before || !ptype_info_opequals_equals || !ptype_info_opnot_equals) return; /* Test calling the dtors */ call_func1(ptype_info_dtor, &t1); /* No effect, since name is NULL */ - t1.name = pmalloc(64); + t1.name = malloc(64); strcpy(t1.name, "foo"); call_func1(ptype_info_dtor, &t1); /* Frees t1.name using 'free' */ @@ -888,7 +869,7 @@ static inline void/*rtti_object_locator*/ *get_obj_locator( void *cppobj ) return (void *)vtable[-1]; } -#ifndef __x86_64__ +#ifdef __i386__ #define DEFINE_RTTI_REF(type, name) type *name #define RTTI_REF(instance, name) &instance.name #define RTTI_REF_SIG0(instance, name, base) RTTI_REF(instance, name) @@ -910,33 +891,36 @@ static void test_rtti(void) DEFINE_RTTI_REF(void, object_locator); } *obj_locator; + struct _rtti_base_descriptor + { + DEFINE_RTTI_REF(type_info, type_descriptor); + int num_base_classes; + struct { + int this_offset; + int vbase_descr; + int vbase_offset; + } this_ptr_offsets; + unsigned int attributes; + }; + + struct _rtti_base_array { + DEFINE_RTTI_REF(struct _rtti_base_descriptor, bases[4]); + }; + + struct _rtti_object_hierarchy { + unsigned int signature; + unsigned int attributes; + int array_len; + DEFINE_RTTI_REF(struct _rtti_base_array, base_classes); + }; + struct rtti_data { type_info type_info[4]; - struct _rtti_base_descriptor - { - DEFINE_RTTI_REF(type_info, type_descriptor); - int num_base_classes; - struct { - int this_offset; - int vbase_descr; - int vbase_offset; - } this_ptr_offsets; - unsigned int attributes; - } base_descriptor[4]; - - struct _rtti_base_array { - DEFINE_RTTI_REF(struct _rtti_base_descriptor, bases[4]); - } base_array; - - struct _rtti_object_hierarchy { - unsigned int signature; - unsigned int attributes; - int array_len; - DEFINE_RTTI_REF(struct _rtti_base_array, base_classes); - } object_hierarchy; - + struct _rtti_base_descriptor base_descriptor[4]; + struct _rtti_base_array base_array; + struct _rtti_object_hierarchy object_hierarchy; struct _object_locator object_locator; } simple_class_rtti = { { {NULL, NULL, "simple_class"} }, @@ -962,11 +946,17 @@ static void test_rtti(void) void *simple_class_vtbl[2] = {&simple_class_rtti.object_locator}; void *simple_class = &simple_class_vtbl[1]; void *child_class_vtbl[2] = {&child_class_rtti.object_locator}; - void *child_class = &child_class_vtbl[1]; + struct { + void *vtbl; + char data[4]; + } child_class = { &child_class_vtbl[1] }; void *simple_class_sig0_vtbl[2] = {&simple_class_sig0_rtti.object_locator}; void *simple_class_sig0 = &simple_class_sig0_vtbl[1]; void *child_class_sig0_vtbl[2] = {&child_class_sig0_rtti.object_locator}; - void *child_class_sig0 = &child_class_sig0_vtbl[1]; + struct { + void *vtbl; + char data[4]; + } child_class_sig0 = { &child_class_sig0_vtbl[1] }; void *virtual_base_class_vtbl[2] = {&virtual_base_class_rtti.object_locator}; int virtual_base_class_vbtbl[2] = {0, 0x100}; struct { @@ -980,12 +970,11 @@ static void test_rtti(void) exception e,b; void *casted; BOOL old_signature; -#ifdef __x86_64__ +#ifndef __i386__ char *base = (char*)GetModuleHandleW(NULL); #endif - if (bAncientVersion || - !p__RTCastToVoid || !p__RTtypeid || !pexception_ctor || !pbad_typeid_ctor + if (!p__RTCastToVoid || !p__RTtypeid || !pexception_ctor || !pbad_typeid_ctor || !p__RTDynamicCast || !pexception_dtor || !pbad_typeid_dtor) return; @@ -1099,46 +1088,32 @@ static void test_demangle_datatype(void) { char * name; struct _demangle demangle[]={ -/* { "BlaBla"," ?? ::Bla", FALSE}, */ - { "ABVVec4@ref2@dice@@","class dice::ref2::Vec4 const &",TRUE}, - { "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$0H@@@", "class CDB_GEN_BIG_ENUM_FLAG<enum CDB_WYSIWYG_BITS_ENUM,7>", TRUE}, - { "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$0HO@@@", "class CDB_GEN_BIG_ENUM_FLAG<enum CDB_WYSIWYG_BITS_ENUM,126>",TRUE}, - { "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$0HOA@@@", "class CDB_GEN_BIG_ENUM_FLAG<enum CDB_WYSIWYG_BITS_ENUM,2016>",TRUE}, - { "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$0HOAA@@@", "class CDB_GEN_BIG_ENUM_FLAG<enum CDB_WYSIWYG_BITS_ENUM,32256>",TRUE}, - { "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$01@@@", "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$01@@@", FALSE}, -/* { "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$011@@@", "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$011@@@",FALSE}, */ + { "BlaBla"," ?? ::Bla", FALSE}, + { "ABVVec4@ref2@dice@@", "class dice::ref2::Vec4 const &", TRUE}, + { "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$0H@@@", + "class CDB_GEN_BIG_ENUM_FLAG<enum CDB_WYSIWYG_BITS_ENUM,7>", TRUE}, + { "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$0HO@@@", + "class CDB_GEN_BIG_ENUM_FLAG<enum CDB_WYSIWYG_BITS_ENUM,126>",TRUE}, + { "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$0HOA@@@", + "class CDB_GEN_BIG_ENUM_FLAG<enum CDB_WYSIWYG_BITS_ENUM,2016>",TRUE}, + { "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$0HOAA@@@", + "class CDB_GEN_BIG_ENUM_FLAG<enum CDB_WYSIWYG_BITS_ENUM,32256>",TRUE}, + { "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$01@@@", + "?AV?$CDB_GEN_BIG_ENUM_FLAG@W4CDB_WYSIWYG_BITS_ENUM@@$01@@@", FALSE}, + { "P8test@@AACXZ", "signed char (__cdecl test::*)(void)", TRUE}, + { "P8test@@BACXZ", "signed char (__cdecl test::*)(void)const ", TRUE}, }; int i, num_test = ARRAY_SIZE(demangle); for (i = 0; i < num_test; i++) { - name = p__unDName(0, demangle[i].mangled, 0, pmalloc, pfree, 0x2800); + name = p__unDName(0, demangle[i].mangled, 0, malloc, free, 0x2800); todo_wine_if (!demangle[i].test_in_wine) ok(name != NULL && !strcmp(name,demangle[i].result), "Got name \"%s\" for %d\n", name, i); - if(name) - pfree(name); + free(name); } } -/* Compare two strings treating multiple spaces (' ', ascii 0x20) in s2 - as single space. Needed for test_demangle as __unDName() returns sometimes - two spaces instead of one in some older native msvcrt dlls. */ -static int strcmp_space(const char *s1, const char *s2) -{ - const char* s2start = s2; - do { - while (*s1 == *s2 && *s1) { - s1++; - s2++; - } - if (*s2 == ' ' && s2 > s2start && *(s2 - 1) == ' ') - s2++; - else - break; - } while (*s1 && *s2); - return *s1 - *s2; -} - static void test_demangle(void) { static struct {const char* in; const char* out; const char *broken; unsigned int flags;} test[] = { @@ -1202,7 +1177,7 @@ static void test_demangle(void) /* 23 */ {"??0streambuf@@QAE@ABV0@@Z", "public: __thiscall streambuf::streambuf(class streambuf const &)"}, /* 24 */ {"??0strstreambuf@@QAE@ABV0@@Z", "public: __thiscall strstreambuf::strstreambuf(class strstreambuf const &)"}, /* 25 */ {"??0strstreambuf@@QAE@H@Z", "public: __thiscall strstreambuf::strstreambuf(int)"}, -/* 26 */ {"??0strstreambuf@@QAE@P6APAXJ@ZP6AXPAX@Z@Z", "public: __thiscall strstreambuf::strstreambuf(void * (__cdecl*)(long),void (__cdecl*)(void *))"}, +/* 26 */ {"??0strstreambuf@@QAE@Q6APAXJ@ZS6AXPAX@Z@Z", "public: __thiscall strstreambuf::strstreambuf(void * (__cdecl*const)(long),void (__cdecl*const volatile)(void *))"}, /* 27 */ {"??0strstreambuf@@QAE@PADH0@Z", "public: __thiscall strstreambuf::strstreambuf(char *,int,char *)"}, /* 28 */ {"??0strstreambuf@@QAE@PAEH0@Z", "public: __thiscall strstreambuf::strstreambuf(unsigned char *,int,unsigned char *)"}, /* 29 */ {"??0strstreambuf@@QAE@XZ", "public: __thiscall strstreambuf::strstreambuf(void)"}, @@ -1237,7 +1212,7 @@ static void test_demangle(void) /* 58 */ {"?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z", "protected: virtual class std::istreambuf_iterator<char,struct std::char_traits<char> > __thiscall std::num_get<char,class std::istreambuf_iterator<char,struct std::char_traits<char> > >::do_get(class std::istreambuf_iterator<char,struct std::char_traits<char> >,class std::istreambuf_iterator<char,struct std::char_trai [...] /* 59 */ {"?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAK@Z", "protected: virtual class std::istreambuf_iterator<char,struct std::char_traits<char> > __thiscall std::num_get<char,class std::istreambuf_iterator<char,struct std::char_traits<char> > >::do_get(class std::istreambuf_iterator<char,struct std::char_traits<char> >,class std::istreambuf_iterator<char,struct std::char_trai [...] /* 60 */ {"?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAM@Z", "protected: virtual class std::istreambuf_iterator<char,struct std::char_traits<char> > __thiscall std::num_get<char,class std::istreambuf_iterator<char,struct std::char_traits<char> > >::do_get(class std::istreambuf_iterator<char,struct std::char_traits<char> >,class std::istreambuf_iterator<char,struct std::char_trai [...] -/* 61 */ {"?_query_new_handler@@YAP6AHI@ZXZ", "int (__cdecl*__cdecl _query_new_handler(void))(unsigned int)"}, +/* 61 */ {"?_query_new_handler@@YAR6AHI@ZXZ", "int (__cdecl*__cdecl _query_new_handler(void))(unsigned int)"}, /* 62 */ {"?register_callback@ios_base@std@@QAEXP6AXW4event@12@AAV12@H@ZH@Z", "public: void __thiscall std::ios_base::register_callback(void (__cdecl*)(enum std::ios_base::event,class std::ios_base &,int),int)"}, /* 63 */ {"?seekg@?$basic_istream@DU?$char_traits@D@std@@@std@@QAEAAV12@JW4seekdir@ios_base@2@@Z", "public: class std::basic_istream<char,struct std::char_traits<char> > & __thiscall std::basic_istream<char,struct std::char_traits<char> >::seekg(long,enum std::ios_base::seekdir)"}, /* 64 */ {"?seekg@?$basic_istream@DU?$char_traits@D@std@@@std@@QAEAAV12@V?$fpos@H@2@@Z", "public: class std::basic_istream<char,struct std::char_traits<char> > & __thiscall std::basic_istream<char,struct std::char_traits<char> >::seekg(class std::fpos<int>)"}, @@ -1325,22 +1300,54 @@ static void test_demangle(void) "??$run@XVTask_Render_Preview@@@QtConcurrent@@YA?AV?$QFuture@X@@PEAVTask_Render_Preview@@P82@EAAXXZ@Z"}, /* 130 */ {"??_E?$TStrArray@$$BY0BAA@D$0BA@@@UAEPAXI@Z", "public: virtual void * __thiscall TStrArray<char [256],16>::`vector deleting destructor'(unsigned int)"}, +/* 131 */ {"??_R0?AVCC@DD@@@8", "class DD::CC `RTTI Type Descriptor'"}, +/* 132 */ {"??$meth@FD@DD@CC@@QAE_NK@Z", "public: bool __thiscall CC::DD::meth<short,char>(unsigned long)"}, +/* 133 */ {"?func@@YAXPIFAH@Z", "void __cdecl func(int __unaligned * __restrict)"}, +/* 135 */ {"?x@@3PAY02HA", "int (* x)[3]"}, +/* 136 */ {"?Qux@Bar@@0PAPAP6AHPAV1@AAH1PAH@ZA", + "private: static int (__cdecl** * Bar::Qux)(class Bar *,int &,int &,int *)"}, /* variation of 105: note white space handling! */ +/* 137 */ {"?x@@3PAW4myenum@@A", "enum myenum * x"}, +/* 138 */ {"?pfunc@@3PAY0E@P6AXF@ZA", "void (__cdecl*(* pfunc)[4])(short)"}, +/* 139 */ {"??$?0AEAVzzz@BB4@AA@@AEAV012@$0A@@?$pair@Vzzz@BB4@AA@@V123@@std@@QEAA@AEAVzzz@BB4@AA@@0@Z", + "public: __cdecl std::pair<class AA::BB4::zzz,class AA::BB4::zzz>::pair<class AA::BB4::zzz,class AA::BB4::zzz><class AA::BB4::zzz & __ptr64,class AA::BB4::zzz & __ptr64,0>(class AA::BB4::zzz & __ptr64,class AA::BB4::zzz & __ptr64) __ptr64"}, +/* 140 */ {"??$?BH@?$foo@N@@QEAAHXZ", "public: __cdecl foo<double>::operator<int> int(void) __ptr64"}, +/* 141 */ {"??Bcastop@@QAEHXZ", "public: __thiscall castop::operator int(void)"}, +/* 142 */ {"??Bcastop@@QAE?BHXZ", "public: __thiscall castop::operator int const (void)"}, +/* 143 */ {"?pfield@@3PTAA@@DT1@", "char const volatile AA::* const volatile pfield"}, +/* 144 */ {"?ptititi1@@3PEQtititi@@IEQ1@", "unsigned int tititi::* __ptr64 __ptr64 ptititi1"}, +/* 145 */ {"?ptititi2@@3PERtititi@@IER1@", "unsigned int const tititi::* __ptr64 const __ptr64 ptititi2"}, +/* 146 */ {"?ptititi3@@3PEStititi@@IES1@", "unsigned int volatile tititi::* __ptr64 volatile __ptr64 ptititi3"}, +/* 147 */ {"?ptititi4@@3PETtititi@@IET1@", "unsigned int const volatile tititi::* __ptr64 const volatile __ptr64 ptititi4"}, +/* 148 */ {"?ptititi4v@@3RETtititi@@IET1@", "unsigned int const volatile tititi::* __ptr64 const volatile __ptr64 ptititi4v"}, +/* 149 */ {"?meth@AAA@@QFCEXXZ", "public: void __thiscall AAA::meth(void)volatile __unaligned "}, +/* 150 */ {"?RegisterModuleUninitializer@<CrtImplementationDetails>@@YAXP$AAVEventHandler@System@@@Z", + "void __cdecl <CrtImplementationDetails>::RegisterModuleUninitializer(class System::EventHandler ^)"}, +/* 151 */ {"?RegisterModuleUninitializer@<CrtImplementationDetails>@@YAXBE$AAVEventHandler@System@@@Z", + "void __cdecl <CrtImplementationDetails>::RegisterModuleUninitializer(class System::EventHandler % __ptr64 volatile)"}, +/* 152 */ {"??$forward@AEAUFFIValue@?1??call@FFIFunctionBinder@@CAHPEAUlua_State@@@Z@@std@@YAAEAUFFIValue@?1??call@" + "FFIFunctionBinder@@CAHPEAUxlua_State@@@Z@AEAU1?1??23@CAH0@Z@@Z", + "struct `private: static int __cdecl FFIFunctionBinder::call(struct xlua_State * __ptr64)'::`2'::FFIValue & " + "__ptr64 __cdecl std::forward<struct `private: static int __cdecl FFIFunctionBinder::call(struct lua_State " + "* __ptr64)'::`2'::FFIValue & __ptr64>(struct `private: static int __cdecl FFIFunctionBinder::call(struct " + "xlua_State * __ptr64)'::`2'::FFIValue & __ptr64)"}, +/* 153 */ {"?$AAA@XX", "AAA<void,void>"}, +/* 154 */ {"?$AAA@", "AAA<>"}, }; - int i, num_test = ARRAY_SIZE(test); + int i; char* name; - for (i = 0; i < num_test; i++) + for (i = 0; i < ARRAY_SIZE(test); i++) { - name = p__unDName(0, test[i].in, 0, pmalloc, pfree, test[i].flags); + name = p__unDName(0, test[i].in, 0, malloc, free, test[i].flags); ok(name != NULL, "%u: unDName failed\n", i); if (!name) continue; - ok( !strcmp_space(test[i].out, name) || - broken(test[i].broken && !strcmp_space(test[i].broken, name)), + ok( !strcmp(test[i].out, name) || + broken(test[i].broken && !strcmp(test[i].broken, name)), "%u: Got name \"%s\"\n", i, name ); - ok( !strcmp_space(test[i].out, name) || - broken(test[i].broken && !strcmp_space(test[i].broken, name)), + ok( !strcmp(test[i].out, name) || + broken(test[i].broken && !strcmp(test[i].broken, name)), "%u: Expected \"%s\"\n", i, test[i].out ); - pfree(name); + free(name); } } diff --git a/modules/rostests/winetests/msvcrt/data.c b/modules/rostests/winetests/msvcrt/data.c index b0acc60b20b..b78bc4f7029 100644 --- a/modules/rostests/winetests/msvcrt/data.c +++ b/modules/rostests/winetests/msvcrt/data.c @@ -32,7 +32,11 @@ #include <errno.h> #include <direct.h> -void __cdecl __getmainargs(int *, char ***, char ***, int, int *); +#ifdef __REACTOS__ +_CRTIMP void __cdecl __getmainargs(int *, char ***, char ***, int, int *); +_CRTIMP void __cdecl __wgetmainargs(int *, wchar_t ***, wchar_t ***, int, int *); +#endif + static int* (__cdecl *p___p___argc)(void); static char*** (__cdecl *p___p___argv)(void); @@ -92,12 +96,12 @@ static void test_initvar( HMODULE hmsvcrt ) winminor = *pp_winminor; winmajor = *pp_winmajor; GetVersionExA( &osvi); - ok( winminor == osvi.dwMinorVersion, "Wrong value for _winminor %02x expected %02x\n", + ok( winminor == osvi.dwMinorVersion, "Wrong value for _winminor %02x expected %02lx\n", winminor, osvi.dwMinorVersion); - ok( winmajor == osvi.dwMajorVersion, "Wrong value for _winmajor %02x expected %02x\n", + ok( winmajor == osvi.dwMajorVersion, "Wrong value for _winmajor %02x expected %02lx\n", winmajor, osvi.dwMajorVersion); ok( winver == ((osvi.dwMajorVersion << 8) | osvi.dwMinorVersion), - "Wrong value for _winver %02x expected %02x\n", + "Wrong value for _winver %02x expected %02lx\n", winver, ((osvi.dwMajorVersion << 8) | osvi.dwMinorVersion)); if( !pp_osver || !pp_osplatform ) { win_skip("_osver variables are not available\n"); @@ -108,10 +112,10 @@ static void test_initvar( HMODULE hmsvcrt ) ok( osver == (osvi.dwBuildNumber & 0xffff) || ((osvi.dwBuildNumber >> 24) == osvi.dwMajorVersion && ((osvi.dwBuildNumber >> 16) & 0xff) == osvi.dwMinorVersion), /* 95/98/ME */ - "Wrong value for _osver %04x expected %04x\n", + "Wrong value for _osver %04x expected %04lx\n", osver, osvi.dwBuildNumber); ok(osplatform == osvi.dwPlatformId, - "Wrong value for _osplatform %x expected %x\n", + "Wrong value for _osplatform %x expected %lx\n", osplatform, osvi.dwPlatformId); } @@ -133,7 +137,7 @@ static void test___getmainargs(void) { int argc, new_argc, mode; char **argv, **new_argv, **envp; - char tmppath[MAX_PATH], filepath[MAX_PATH]; + char tmppath[MAX_PATH], filepath[MAX_PATH + 14]; FILE *f; ok(GetTempPathA(MAX_PATH, tmppath) != 0, "GetTempPath failed\n"); @@ -194,7 +198,7 @@ static void test___getmainargs(void) static void test___getmainargs_parent(char *name) { char cmdline[3*MAX_PATH]; - char tmppath[MAX_PATH], filepath[MAX_PATH]; + char tmppath[MAX_PATH], filepath[MAX_PATH + 14]; STARTUPINFOA startup; PROCESS_INFORMATION proc; FILE *f; @@ -218,7 +222,7 @@ static void test___getmainargs_parent(char *name) memset(&startup, 0, sizeof(startup)); startup.cb = sizeof(startup); CreateProcessA(NULL, cmdline, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE|NORMAL_PRIORITY_CLASS, NULL, NULL, &startup, &proc); - winetest_wait_child_process(proc.hProcess); + wait_child_process(proc.hProcess); _unlink(filepath); sprintf(filepath, "%swine_test\\a", tmppath); diff --git a/modules/rostests/winetests/msvcrt/dir.c b/modules/rostests/winetests/msvcrt/dir.c index 210cf3983cd..a2a704d85d3 100644 --- a/modules/rostests/winetests/msvcrt/dir.c +++ b/modules/rostests/winetests/msvcrt/dir.c @@ -138,36 +138,6 @@ static void test_makepath(void) } } -static const WCHAR expected0[] = {'\0','X','X','X','X','X','X','X','X','X','X','X','X'}; -static const WCHAR expected1[] = {'\0','X','X','X','X','X','X','X','X','X','X','X','X'}; -static const WCHAR expected2[] = {'\0',':','X','X','X','X','X','X','X','X','X','X','X'}; -static const WCHAR expected3[] = {'\0',':','d','X','X','X','X','X','X','X','X','X','X'}; -static const WCHAR expected4[] = {'\0',':','d','\\','X','X','X','X','X','X','X','X','X'}; -static const WCHAR expected5[] = {'\0',':','d','\\','f','X','X','X','X','X','X','X','X'}; -static const WCHAR expected6[] = {'\0',':','d','\\','f','i','X','X','X','X','X','X','X'}; -static const WCHAR expected7[] = {'\0',':','d','\\','f','i','l','X','X','X','X','X','X'}; -static const WCHAR expected8[] = {'\0',':','d','\\','f','i','l','e','X','X','X','X','X'}; -static const WCHAR expected9[] = {'\0',':','d','\\','f','i','l','e','.','X','X','X','X'}; -static const WCHAR expected10[] = {'\0',':','d','\\','f','i','l','e','.','e','X','X','X'}; -static const WCHAR expected11[] = {'\0',':','d','\\','f','i','l','e','.','e','x','X','X'}; - -static const WCHAR expected12[] = {'\0',':','X','X','X','X','X','X','X','X'}; -static const WCHAR expected13[] = {'\0',':','d','X','X','X','X','X','X','X'}; -static const WCHAR expected14[] = {'\0',':','d','i','X','X','X','X','X','X'}; -static const WCHAR expected15[] = {'\0',':','d','i','r','X','X','X','X','X'}; -static const WCHAR expected16[] = {'\0',':','d','i','r','\\','X','X','X','X'}; - -static const WCHAR expected17[] = {'\0','o','o'}; -static const WCHAR expected18[] = {'\0','o','o','\0','X'}; -static const WCHAR expected19[] = {'\0','o','o','\0'}; -static const WCHAR expected20[] = {'\0','o','o','\0','X','X','X','X','X'}; -static const WCHAR expected21[] = {'\0','o','o','\\','f','i','l','X','X'}; -static const WCHAR expected22[] = {'\0','o','o','\0','X','X','X','X','X','X','X','X','X'}; -static const WCHAR expected23[] = {'\0','o','o','\\','f','i','l','X','X','X','X','X','X'}; -static const WCHAR expected24[] = {'\0','o','o','\\','f','i','l','e','.','e','x','X','X'}; -static const WCHAR expected25[] = {'\0','o','o','\0','X','X','X','X'}; -static const WCHAR expected26[] = {'\0','o','o','.','e','x','X','X'}; - typedef struct { const char* buffer; @@ -184,35 +154,35 @@ typedef struct static const makepath_s_case makepath_s_cases[] = { /* Behavior with directory parameter containing backslash. */ - {NULL, 1, "c:", "d\\", "file", "ext", "\0XXXXXXXXXXXX", expected0, 13}, - {NULL, 2, "c:", "d\\", "file", "ext", "\0XXXXXXXXXXXX", expected1, 13}, - {NULL, 3, "c:", "d\\", "file", "ext", "\0:XXXXXXXXXXX", expected2, 13}, - {NULL, 4, "c:", "d\\", "file", "ext", "\0:dXXXXXXXXXX", expected3, 13}, - {NULL, 5, "c:", "d\\", "file", "ext", "\0:d\\XXXXXXXXX", expected4, 13}, - {NULL, 6, "c:", "d\\", "file", "ext", "\0:d\\fXXXXXXXX", expected5, 13}, - {NULL, 7, "c:", "d\\", "file", "ext", "\0:d\\fiXXXXXXX", expected6, 13}, - {NULL, 8, "c:", "d\\", "file", "ext", "\0:d\\filXXXXXX", expected7, 13}, - {NULL, 9, "c:", "d\\", "file", "ext", "\0:d\\fileXXXXX", expected8, 13}, - {NULL, 10, "c:", "d\\", "file", "ext", "\0:d\\file.XXXX", expected9, 13}, - {NULL, 11, "c:", "d\\", "file", "ext", "\0:d\\file.eXXX", expected10, 13}, - {NULL, 12, "c:", "d\\", "file", "ext", "\0:d\\file.exXX", expected11, 13}, + {NULL, 1, "c:", "d\\", "file", "ext", "\0XXXXXXXXXXXX", L"\0XXXXXXXXXXXX", 13}, + {NULL, 2, "c:", "d\\", "file", "ext", "\0XXXXXXXXXXXX", L"\0XXXXXXXXXXXX", 13}, + {NULL, 3, "c:", "d\\", "file", "ext", "\0:XXXXXXXXXXX", L"\0:XXXXXXXXXXX", 13}, + {NULL, 4, "c:", "d\\", "file", "ext", "\0:dXXXXXXXXXX", L"\0:dXXXXXXXXXX", 13}, + {NULL, 5, "c:", "d\\", "file", "ext", "\0:d\\XXXXXXXXX", L"\0:d\\XXXXXXXXX", 13}, + {NULL, 6, "c:", "d\\", "file", "ext", "\0:d\\fXXXXXXXX", L"\0:d\\fXXXXXXXX", 13}, + {NULL, 7, "c:", "d\\", "file", "ext", "\0:d\\fiXXXXXXX", L"\0:d\\fiXXXXXXX", 13}, + {NULL, 8, "c:", "d\\", "file", "ext", "\0:d\\filXXXXXX", L"\0:d\\filXXXXXX", 13}, + {NULL, 9, "c:", "d\\", "file", "ext", "\0:d\\fileXXXXX", L"\0:d\\fileXXXXX", 13}, + {NULL, 10, "c:", "d\\", "file", "ext", "\0:d\\file.XXXX", L"\0:d\\file.XXXX", 13}, + {NULL, 11, "c:", "d\\", "file", "ext", "\0:d\\file.eXXX", L"\0:d\\file.eXXX", 13}, + {NULL, 12, "c:", "d\\", "file", "ext", "\0:d\\file.exXX", L"\0:d\\file.exXX", 13}, /* Behavior with directory parameter lacking backslash. */ - {NULL, 3, "c:", "dir", "f", "ext", "\0:XXXXXXXX", expected12, 10}, - {NULL, 4, "c:", "dir", "f", "ext", "\0:dXXXXXXX", expected13, 10}, - {NULL, 5, "c:", "dir", "f", "ext", "\0:diXXXXXX", expected14, 10}, - {NULL, 6, "c:", "dir", "f", "ext", "\0:dirXXXXX", expected15, 10}, - {NULL, 7, "c:", "dir", "f", "ext", "\0:dir\\XXXX", expected16, 10}, + {NULL, 3, "c:", "dir", "f", "ext", "\0:XXXXXXXX", L"\0:XXXXXXXX", 10}, + {NULL, 4, "c:", "dir", "f", "ext", "\0:dXXXXXXX", L"\0:dXXXXXXX", 10}, + {NULL, 5, "c:", "dir", "f", "ext", "\0:diXXXXXX", L"\0:diXXXXXX", 10}, + {NULL, 6, "c:", "dir", "f", "ext", "\0:dirXXXXX", L"\0:dirXXXXX", 10}, + {NULL, 7, "c:", "dir", "f", "ext", "\0:dir\\XXXX", L"\0:dir\\XXXX", 10}, /* Behavior with overlapped buffer. */ - {"foo", 2, USE_BUFF, NULL, NULL, NULL, "\0oo", expected17, 3}, - {"foo", 4, NULL, USE_BUFF, NULL, NULL, "\0oo\0X", expected18, 5}, - {"foo", 3, NULL, NULL, USE_BUFF, NULL, "\0oo\0", expected19, 4}, - {"foo", 4, NULL, USE_BUFF, "file", NULL, "\0oo\0XXXXX", expected20, 9}, - {"foo", 8, NULL, USE_BUFF, "file", NULL, "\0oo\\filXX", expected21, 9}, - {"foo", 4, NULL, USE_BUFF, "file", "ext", "\0oo\0XXXXXXXXX", expected22, 13}, - {"foo", 8, NULL, USE_BUFF, "file", "ext", "\0oo\\filXXXXXX", expected23, 13}, - {"foo", 12, NULL, USE_BUFF, "file", "ext", "\0oo\\file.exXX", expected24, 13}, - {"foo", 4, NULL, NULL, USE_BUFF, "ext", "\0oo\0XXXX", expected25, 8}, - {"foo", 7, NULL, NULL, USE_BUFF, "ext", "\0oo.exXX", expected26, 8}, + {"foo", 2, USE_BUFF, NULL, NULL, NULL, "\0oo", L"\0oo", 3}, + {"foo", 4, NULL, USE_BUFF, NULL, NULL, "\0oo\0X", L"\0oo\0X", 5}, + {"foo", 3, NULL, NULL, USE_BUFF, NULL, "\0oo\0", L"\0oo", 4}, + {"foo", 4, NULL, USE_BUFF, "file", NULL, "\0oo\0XXXXX", L"\0oo\0XXXXX", 9}, + {"foo", 8, NULL, USE_BUFF, "file", NULL, "\0oo\\filXX", L"\0oo\\filXX", 9}, + {"foo", 4, NULL, USE_BUFF, "file", "ext", "\0oo\0XXXXXXXXX", L"\0oo\0XXXXXXXXX", 13}, + {"foo", 8, NULL, USE_BUFF, "file", "ext", "\0oo\\filXXXXXX", L"\0oo\\filXXXXXX", 13}, + {"foo", 12, NULL, USE_BUFF, "file", "ext", "\0oo\\file.exXX", L"\0oo\\file.exXX", 13}, + {"foo", 4, NULL, NULL, USE_BUFF, "ext", "\0oo\0XXXX", L"\0oo\0XXXX", 8}, + {"foo", 7, NULL, NULL, USE_BUFF, "ext", "\0oo.exXX", L"\0oo.exXX", 8}, }; static void test_makepath_s(void) @@ -438,10 +408,6 @@ static void test_searchenv(void) "\\search_env_test\\dir3longer\\3.dat" }; - const WCHAR env_w[] = {'T','E','S','T','_','P','A','T','H',0}; - const WCHAR dat1_w[] = {'1','.','d','a','t',0}; - const WCHAR dat3_w[] = {'3','.','d','a','t',0}; - char env1[4*MAX_PATH], env2[4*MAX_PATH], tmppath[MAX_PATH], path[2*MAX_PATH]; char result[MAX_PATH], exp[2*MAX_PATH]; WCHAR result_w[MAX_PATH]; @@ -510,13 +476,13 @@ static void test_searchenv(void) } memset(result_w, 'x', sizeof(result_w)); - _wsearchenv(dat1_w, env_w, result_w); + _wsearchenv(L"1.dat", L"TEST_PATH", result_w); WideCharToMultiByte(CP_ACP, 0, result_w, -1, result, MAX_PATH, NULL, NULL); ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); if (p_wsearchenv_s) { memset(result_w, 'x', sizeof(result_w)); - i = p_wsearchenv_s(dat1_w, env_w, result_w, MAX_PATH); + i = p_wsearchenv_s(L"1.dat", L"TEST_PATH", result_w, MAX_PATH); ok(!i, "wsearchenv_s returned %d\n", i); ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); } @@ -535,13 +501,13 @@ static void test_searchenv(void) } memset(result_w, 'x', sizeof(result_w)); - _wsearchenv(dat3_w, env_w, result_w); + _wsearchenv(L"3.dat", L"TEST_PATH", result_w); WideCharToMultiByte(CP_ACP, 0, result_w, -1, result, MAX_PATH, NULL, NULL); ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); if (p_wsearchenv_s) { memset(result_w, 'x', sizeof(result_w)); - i = p_wsearchenv_s(dat3_w, env_w, result_w, MAX_PATH); + i = p_wsearchenv_s(L"3.dat", L"TEST_PATH", result_w, MAX_PATH); ok(!i, "wsearchenv_s returned %d\n", i); ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); } @@ -561,13 +527,13 @@ static void test_searchenv(void) } memset(result_w, 'x', sizeof(result_w)); - _wsearchenv(dat1_w, env_w, result_w); + _wsearchenv(L"1.dat", L"TEST_PATH", result_w); WideCharToMultiByte(CP_ACP, 0, result_w, -1, result, MAX_PATH, NULL, NULL); ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); if (p_wsearchenv_s) { memset(result_w, 'x', sizeof(result_w)); - i = p_wsearchenv_s(dat1_w, env_w, result_w, MAX_PATH); + i = p_wsearchenv_s(L"1.dat", L"TEST_PATH", result_w, MAX_PATH); ok(!i, "wsearchenv_s returned %d\n", i); ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); } @@ -586,17 +552,31 @@ static void test_searchenv(void) } memset(result_w, 'x', sizeof(result_w)); - _wsearchenv(dat3_w, env_w, result_w); + _wsearchenv(L"3.dat", L"TEST_PATH", result_w); WideCharToMultiByte(CP_ACP, 0, result_w, -1, result, MAX_PATH, NULL, NULL); ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); if (p_wsearchenv_s) { memset(result_w, 'x', sizeof(result_w)); - i = p_wsearchenv_s(dat3_w, env_w, result_w, MAX_PATH); + i = p_wsearchenv_s(L"3.dat", L"TEST_PATH", result_w, MAX_PATH); ok(!i, "wsearchenv_s returned %d\n", i); ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); } + strcpy(env1, "TEST_PATH="); + strcat(env1, tmppath); + strcat(env1, "\"\\search_env_test\\\"d\"i\"r\"1"); + putenv(env1); + strcpy(exp, tmppath); + strcat(exp, files[0]); + _searchenv("1.dat", "TEST_PATH", result); + ok(!strcmp(result, exp), "got %s, expected '%s'\n", result, exp); + + strcat(env1, ";"); + putenv(env1); + _searchenv("1.dat", "TEST_PATH", result); + ok(!result[0], "got %s, expected ''\n", result); + putenv("TEST_PATH="); for (i=ARRAY_SIZE(files)-1; i>=0; i--) { diff --git a/modules/rostests/winetests/msvcrt/environ.c b/modules/rostests/winetests/msvcrt/environ.c index b8e0ae6251a..9951c5b1308 100644 --- a/modules/rostests/winetests/msvcrt/environ.c +++ b/modules/rostests/winetests/msvcrt/environ.c @@ -19,7 +19,15 @@ */ #include "wine/test.h" +#include <errno.h> #include <stdlib.h> +#include <process.h> +#include <winnls.h> + +#ifdef __REACTOS__ +_CRTIMP void __cdecl __getmainargs(int *, char ***, char ***, int, int *); +_CRTIMP void __cdecl __wgetmainargs(int *, wchar_t ***, wchar_t ***, int, int *); +#endif static const char *a_very_long_env_string = "LIBRARY_PATH=" @@ -42,13 +50,15 @@ static const char *a_very_long_env_string = "/usr/lib/mingw32/3.4.2/;" "/usr/lib/"; -void __cdecl __getmainargs(int *, char ***, char ***, int, int *); -void __cdecl __wgetmainargs(int *, wchar_t ***, wchar_t ***, int, int *); - static char ***(__cdecl *p__p__environ)(void); static WCHAR ***(__cdecl *p__p__wenviron)(void); -static void (*p_get_environ)(char ***); -static void (*p_get_wenviron)(WCHAR ***); +static char ***(__cdecl *p__p___initenv)(void); +static wchar_t ***(__cdecl *p__p___winitenv)(void); +static void (__cdecl *p_get_environ)(char ***); +static void (__cdecl *p_get_wenviron)(WCHAR ***); +static errno_t (__cdecl *p_putenv_s)(const char*, const char*); +static errno_t (__cdecl *p_wputenv_s)(const wchar_t*, const wchar_t*); +static errno_t (__cdecl *p_getenv_s)(size_t*, char*, size_t, const char*); static char ***p_environ; static WCHAR ***p_wenviron; @@ -59,10 +69,15 @@ static void init(void) p__p__environ = (void *)GetProcAddress(hmod, "__p__environ"); p__p__wenviron = (void *)GetProcAddress(hmod, "__p__wenviron"); + p__p___initenv = (void *)GetProcAddress(hmod, "__p___initenv"); + p__p___winitenv = (void *)GetProcAddress(hmod, "__p___winitenv"); p_environ = (void *)GetProcAddress(hmod, "_environ"); p_wenviron = (void *)GetProcAddress(hmod, "_wenviron"); p_get_environ = (void *)GetProcAddress(hmod, "_get_environ"); p_get_wenviron = (void *)GetProcAddress(hmod, "_get_wenviron"); + p_putenv_s = (void *)GetProcAddress(hmod, "_putenv_s"); + p_wputenv_s = (void *)GetProcAddress(hmod, "_wputenv_s"); + p_getenv_s = (void *)GetProcAddress(hmod, "getenv_s"); } static void test_system(void) @@ -74,30 +89,46 @@ static void test_system(void) ok(ret == 0, "Expected system to return 0, got %d\n", ret); } -static void test__environ(void) +static unsigned env_get_entry_countA( char **env ) { - int argc; - char **argv, **envp = NULL; - int i, mode = 0; + unsigned count; - ok( p_environ != NULL, "Expected the pointer to _environ to be non-NULL\n" ); - if (p_environ) - ok( *p_environ != NULL, "Expected _environ to be initialized on startup\n" ); + if (!env) return 0; + for (count = 0; env[count] != NULL; count++) {} + return count; +} - if (!p_environ || !*p_environ) - { - skip( "_environ pointers are not valid\n" ); - return; - } +static wchar_t *env_get_valueW( wchar_t **envp, const wchar_t *var ) +{ + unsigned i; + size_t len = wcslen( var ); - /* Examine the returned pointer from __p__environ(), if available. */ - if (p__p__environ) + if (!envp) return NULL; + for (i = 0; envp[i] != NULL; i++) { - ok( *p__p__environ() == *p_environ, - "Expected _environ pointers to be identical\n" ); + wchar_t *ptr; + + if (!(ptr = wcschr( envp[i], L'=' ))) continue; + + if (ptr - envp[i] == len && !memcmp( envp[i], var, len * sizeof(wchar_t) )) + return ptr + 1; } + return NULL; +} + +static void test__environ(void) +{ + int argc; + char **argv, **envp = NULL, **initenv = NULL; + int mode = 0; + + ok( p_environ != NULL, "Expected the pointer to _environ to be non-NULL\n" ); + ok( *p_environ != NULL, "Expected _environ to be initialized on startup\n" ); + + if (sizeof(void*) != sizeof(int)) + ok( !p__p__environ, "__p__environ() should be 32-bit only\n"); else - skip( "__p__environ() is not available\n" ); + ok( *p__p__environ() == *p_environ, "Expected _environ pointers to be identical\n" ); if (p_get_environ) { @@ -109,76 +140,74 @@ static void test__environ(void) else win_skip( "_get_environ() is not available\n" ); + if (p__p___initenv) + { + initenv = *p__p___initenv(); + + ok( initenv == *p_environ, + "Expected _environ to be equal to initial env\n" ); + } + else + skip( "__p___initenv() is not available\n" ); + /* Note that msvcrt from Windows versions older than Vista * expects the mode pointer parameter to be valid.*/ __getmainargs(&argc, &argv, &envp, 0, &mode); - ok( envp != NULL, "Expected initial environment block pointer to be non-NULL\n" ); - if (!envp) - { - skip( "Initial environment block pointer is not valid\n" ); - return; - } + ok( envp != NULL, + "Expected initial environment block pointer to be non-NULL\n" ); + ok( envp == *p_environ, + "Expected initial environment to be equal to _environ\n" ); - for (i = 0; ; i++) + ok( _putenv("cat=dog") == 0, "failed setting cat=dog\n" ); + if (p__p___initenv) { - if ((*p_environ)[i]) - { - ok( envp[i] != NULL, "Expected environment block pointer element to be non-NULL\n" ); - ok( !strcmp((*p_environ)[i], envp[i]), - "Expected _environ and environment block pointer strings (%s vs. %s) to match\n", - (*p_environ)[i], envp[i] ); - } - else - { - ok( !envp[i], "Expected environment block pointer element to be NULL, got %p\n", envp[i] ); - break; - } + char **retptr = *p__p___initenv(); + + ok( retptr != *p_environ, + "Expected _environ[] not to be equal to initial env\n" ); + ok( retptr == initenv, + "Unexpected modification of initial env\n" ); } + ok( _putenv("cat=") == 0, "failed setting cat=\n" ); } static void test__wenviron(void) { - static const WCHAR cat_eq_dogW[] = {'c','a','t','=','d','o','g',0}; - static const WCHAR cat_eqW[] = {'c','a','t','=',0}; - int argc; char **argv, **envp = NULL; WCHAR **wargv, **wenvp = NULL; - int i, mode = 0; + int mode = 0; ok( p_wenviron != NULL, "Expected the pointer to _wenviron to be non-NULL\n" ); - if (p_wenviron) - ok( *p_wenviron == NULL, "Expected _wenviron to be NULL, got %p\n", *p_wenviron ); - else - { - win_skip( "Pointer to _wenviron is not valid\n" ); - return; - } + ok( !*p_wenviron, "Expected _wenviron[] to be NULL, got %p\n", *p_wenviron ); - /* Examine the returned pointer from __p__wenviron(), if available. */ - if (p__p__wenviron) - { - ok( *p__p__wenviron() == NULL, - "Expected _wenviron pointers to be NULL\n" ); - } + if (sizeof(void*) != sizeof(int)) + ok( !p__p__wenviron, "__p__wenviron() should be 32-bit only\n"); else - skip( "__p__wenviron() is not available\n" ); + ok( !*p__p__wenviron(), "Expected _wenviron to be NULL, got %p\n", *p_wenviron ); if (p_get_wenviron) { WCHAR **retptr; p_get_wenviron(&retptr); - ok( retptr == NULL, - "Expected _wenviron pointers to be NULL\n" ); + ok( retptr == *p_wenviron, "Expected _wenviron pointers to be NULL\n" ); } else win_skip( "_get_wenviron() is not available\n" ); + if (p__p___winitenv) + { + wchar_t ***retptr = p__p___winitenv(); + ok( !*retptr, "Expected initial env to be NULL\n" ); + } + else + skip( "__p___winitenv() is not available\n" ); + /* __getmainargs doesn't initialize _wenviron. */ __getmainargs(&argc, &argv, &envp, 0, &mode); - ok( *p_wenviron == NULL, "Expected _wenviron to be NULL, got %p\n", *p_wenviron); + ok( !*p_wenviron, "Expected _wenviron to be NULL\n"); ok( envp != NULL, "Expected initial environment block pointer to be non-NULL\n" ); if (!envp) { @@ -188,24 +217,31 @@ static void test__wenviron(void) /* Neither does calling the non-Unicode environment manipulation functions. */ ok( _putenv("cat=dog") == 0, "failed setting cat=dog\n" ); - ok( *p_wenviron == NULL, "Expected _wenviron to be NULL, got %p\n", *p_wenviron); - ok( _putenv("cat=") == 0, "failed deleting cat\n" ); + ok( !*p_wenviron, "Expected _wenviron to be NULL\n" ); /* _wenviron isn't initialized until __wgetmainargs is called or * one of the Unicode environment manipulation functions is called. */ - ok( _wputenv(cat_eq_dogW) == 0, "failed setting cat=dog\n" ); + ok( _wputenv(L"cat=dog2") == 0, "failed setting cat=dog2\n" ); ok( *p_wenviron != NULL, "Expected _wenviron to be non-NULL\n" ); - ok( _wputenv(cat_eqW) == 0, "failed deleting cat\n" ); __wgetmainargs(&argc, &wargv, &wenvp, 0, &mode); - - ok( *p_wenviron != NULL, "Expected _wenviron to be non-NULL\n" ); ok( wenvp != NULL, "Expected initial environment block pointer to be non-NULL\n" ); - if (!wenvp) + ok( wenvp == *p_wenviron, "Expected initial environment to be _wenviron[]\n" ); + + if (p__p___winitenv) { - skip( "Initial environment block pointer is not valid\n" ); - return; + wchar_t ***retptr = p__p___winitenv(); + wchar_t *value; + + ok( *retptr != NULL, "Expected *__p___winitenv() to be NULL\n" ); + ok( *retptr != *p_wenviron, + "Expected _wenviron to be different from __p___winitenv() %p %p\n", *retptr, *p_wenviron ); + /* test that w-initial env is derived from current _environ[] and not from ansi initial env */ + value = env_get_valueW( *retptr, L"cat" ); + ok( value && !wcscmp( value, L"dog" ), + "Expecting initial env to be derived from current env (got %ls)\n", value ); } + _putenv("cat="); /* Examine the returned pointer from __p__wenviron(), * if available, after _wenviron is initialized. */ @@ -222,29 +258,27 @@ static void test__wenviron(void) ok( retptr == *p_wenviron, "Expected _wenviron pointers to be identical\n" ); } - - for (i = 0; ; i++) - { - if ((*p_wenviron)[i]) - { - ok( wenvp[i] != NULL, "Expected environment block pointer element to be non-NULL\n" ); - ok( !winetest_strcmpW((*p_wenviron)[i], wenvp[i]), - "Expected _wenviron and environment block pointer strings (%s vs. %s) to match\n", - wine_dbgstr_w((*p_wenviron)[i]), wine_dbgstr_w(wenvp[i]) ); - } - else - { - ok( !wenvp[i], "Expected environment block pointer element to be NULL, got %p\n", wenvp[i] ); - break; - } - } } static void test_environment_manipulation(void) { + char buf[256]; + errno_t ret; + size_t len; + unsigned count; + char* first; + char* second; + ok( _putenv("cat=") == 0, "_putenv failed on deletion of nonexistent environment variable\n" ); ok( _putenv("cat=dog") == 0, "failed setting cat=dog\n" ); ok( strcmp(getenv("cat"), "dog") == 0, "getenv did not return 'dog'\n" ); + if (p_getenv_s) + { + ret = p_getenv_s(&len, buf, sizeof(buf), "cat"); + ok( !ret, "getenv_s returned %d\n", ret ); + ok( len == 4, "getenv_s returned length is %Id\n", len); + ok( !strcmp(buf, "dog"), "getenv_s did not return 'dog'\n"); + } ok( _putenv("cat=") == 0, "failed deleting cat\n" ); ok( _putenv("=") == -1, "should not accept '=' as input\n" ); @@ -252,16 +286,190 @@ static void test_environment_manipulation(void) ok( _putenv(a_very_long_env_string) == 0, "_putenv failed for long environment string\n"); ok( getenv("nonexistent") == NULL, "getenv should fail with nonexistent var name\n" ); + + if (p_putenv_s) + { + ret = p_putenv_s(NULL, "dog"); + ok( ret == EINVAL, "_putenv_s returned %d\n", ret); + ret = p_putenv_s("cat", NULL); + ok( ret == EINVAL, "_putenv_s returned %d\n", ret); + ret = p_putenv_s("a=b", NULL); + ok( ret == EINVAL, "_putenv_s returned %d\n", ret); + ret = p_putenv_s("cat", "a=b"); + ok( !ret, "_putenv_s returned %d\n", ret); + ret = p_putenv_s("cat", ""); + ok( !ret, "_putenv_s returned %d\n", ret); + } + + if (p_wputenv_s) + { + ret = p_wputenv_s(NULL, L"dog"); + ok( ret == EINVAL, "_wputenv_s returned %d\n", ret); + ret = p_wputenv_s(L"cat", NULL); + ok( ret == EINVAL, "_wputenv_s returned %d\n", ret); + ret = p_wputenv_s(L"a=b", NULL); + ok( ret == EINVAL, "_wputenv_s returned %d\n", ret); + ret = p_wputenv_s(L"cat", L"a=b"); + ok( !ret, "_wputenv_s returned %d\n", ret); + ret = p_wputenv_s(L"cat", L""); + ok( !ret, "_wputenv_s returned %d\n", ret); + } + + if (p_getenv_s) + { + buf[0] = 'x'; + len = 1; + errno = 0xdeadbeef; + ret = p_getenv_s(&len, buf, sizeof(buf), "nonexistent"); + ok( !ret, "_getenv_s returned %d\n", ret); + ok( !len, "getenv_s returned length is %Id\n", len); + ok( !buf[0], "buf = %s\n", buf); + ok( errno == 0xdeadbeef, "errno = %d\n", errno); + + buf[0] = 'x'; + len = 1; + errno = 0xdeadbeef; + ret = p_getenv_s(&len, buf, sizeof(buf), NULL); + ok( !ret, "_getenv_s returned %d\n", ret); + ok( !len, "getenv_s returned length is %Id\n", len); + ok( !buf[0], "buf = %s\n", buf); + ok( errno == 0xdeadbeef, "errno = %d\n", errno); + } + + /* test stability of _environ[] pointers */ + ok( _putenv( "__winetest_cat=" ) == 0, "Couldn't reset env var\n" ); + ok( _putenv( "__winetest_dog=" ) == 0, "Couldn't reset env var\n" ); + count = env_get_entry_countA( *p_environ ); + ok( _putenv( "__winetest_cat=mew") == 0, "Couldn't set env var\n" ); + ok( !strcmp( (*p_environ)[count], "__winetest_cat=mew"), "Unexpected env var value\n" ); + first = (*p_environ)[count]; + ok( getenv("__winetest_cat") == strchr( (*p_environ)[count], '=') + 1, "Expected getenv() to return pointer inside _environ[] entry\n" ); + ok( _putenv( "__winetest_dog=bark" ) == 0, "Couldn't set env var\n" ); + ok( !strcmp( (*p_environ)[count + 1], "__winetest_dog=bark" ), "Unexpected env var value\n" ); + ok( getenv( "__winetest_dog" ) == strchr( (*p_environ)[count + 1], '=' ) + 1, "Expected getenv() to return pointer inside _environ[] entry\n" ); + ok( first == (*p_environ)[count], "Expected stability of _environ[count] pointer\n" ); + second = (*p_environ)[count + 1]; + ok( count + 2 == env_get_entry_countA( *p_environ ), "Unexpected count\n" ); + + ok( _putenv( "__winetest_cat=purr" ) == 0, "Couldn't set env var\n" ); + ok( !strcmp( (*p_environ)[count], "__winetest_cat=purr" ), "Unexpected env var value\n" ); + ok( getenv( "__winetest_cat" ) == strchr( (*p_environ)[count], '=' ) + 1, "Expected getenv() to return pointer inside _environ[] entry\n" ); + ok( second == (*p_environ)[count + 1], "Expected stability of _environ[count] pointer\n" ); + ok( !strcmp( (*p_environ)[count + 1], "__winetest_dog=bark" ), "Couldn't get env var value\n" ); + ok( getenv( "__winetest_dog" ) == strchr( (*p_environ)[count + 1], '=' ) + 1, "Expected getenv() to return pointer inside _environ[] entry\n" ); + ok( count + 2 == env_get_entry_countA( *p_environ ), "Unexpected count\n" ); + ok( _putenv( "__winetest_cat=" ) == 0, "Couldn't reset env vat\n" ); + ok( second == (*p_environ)[count], "Expected _environ[count] to be second\n" ); + ok( !strcmp( (*p_environ)[count], "__winetest_dog=bark" ), "Unexpected env var value\n" ); + ok( count + 1 == env_get_entry_countA( *p_environ ), "Unexpected count\n" ); + ok( _putenv( "__winetest_dog=" ) == 0, "Couldn't reset env var\n" ); + ok( count == env_get_entry_countA( *p_environ ), "Unexpected count\n" ); + + /* in putenv, only changed variable is updated (no other reload of kernel info is done) */ + ret = SetEnvironmentVariableA( "__winetest_cat", "meow" ); + ok( ret, "SetEnvironmentVariableA failed: %lu\n", GetLastError() ); + ok( _putenv( "__winetest_dog=bark" ) == 0, "Couldn't set env var\n" ); + ok( getenv( "__winetest_cat" ) == NULL, "msvcrt env cache shouldn't have been updated\n" ); + ok( _putenv( "__winetest_cat=" ) == 0, "Couldn't reset env var\n" ); + ok( _putenv( "__winetest_dog=" ) == 0, "Couldn't reset env var\n" ); + + /* test setting unicode bits */ + count = env_get_entry_countA( *p_environ ); + ret = WideCharToMultiByte( CP_ACP, 0, L"\u263a", -1, buf, ARRAY_SIZE(buf), 0, 0 ); + ok( ret, "WideCharToMultiByte failed: %lu\n", GetLastError() ); + ok( _wputenv( L"__winetest_cat=\u263a" ) == 0, "Couldn't set env var\n" ); + ok( _wgetenv( L"__winetest_cat" ) && !wcscmp( _wgetenv( L"__winetest_cat" ), L"\u263a" ), "Couldn't retrieve env var\n" ); + ok( getenv( "__winetest_cat" ) && !strcmp( getenv( "__winetest_cat" ), buf ), "Couldn't retrieve env var\n" ); + ok( _wputenv( L"__winetest_cat=" ) == 0, "Couldn't reset env var\n" ); + + ret = WideCharToMultiByte( CP_ACP, 0, L"__winetest_\u263a", -1, buf, ARRAY_SIZE(buf), 0, 0 ); + ok( ret, "WideCharToMultiByte failed: %lu\n", GetLastError() ); + ok( _wputenv( L"__winetest_\u263a=bark" ) == 0, "Couldn't set env var\n" ); + ok( _wgetenv( L"__winetest_\u263a" ) && !wcscmp( _wgetenv( L"__winetest_\u263a" ), L"bark"), "Couldn't retrieve env var\n" ); + ok( getenv( buf ) && !strcmp( getenv( buf ), "bark"), "Couldn't retrieve env var %s\n", wine_dbgstr_a(buf) ); + ok( _wputenv( L"__winetest_\u263a=" ) == 0, "Couldn't reset env var\n" ); + ok( count == env_get_entry_countA( *p_environ ), "Unexpected modification of _environ[]\n" ); +} + +static void test_child_env(char** argv) +{ + STARTUPINFOA si = {sizeof(si)}; + WCHAR *cur_env, *env, *p, *q; + PROCESS_INFORMATION pi; + char tmp[1024]; + BOOL ret; + int len; + + cur_env = GetEnvironmentStringsW(); + ok( cur_env != NULL, "GetEnvironemntStrings failed\n" ); + + p = cur_env; + while (*p) p += wcslen( p ) + 1; + len = p - cur_env; + env = malloc( (len + 1024) * sizeof(*env) ); + memcpy(env, cur_env, len * sizeof(*env) ); + q = env + len; + FreeEnvironmentStringsW( cur_env ); + + wcscpy( q, L"__winetest_dog=bark" ); + q += wcslen( L"__winetest_dog=bark" ) + 1; + wcscpy( q, L"__winetest_\u263a=\u03b2" ); + q += wcslen( L"__winetest_\u263a=\u03b2" ) + 1; + *q = 0; + + snprintf( tmp, sizeof(tmp), "%s %s create", argv[0], argv[1] ); + ret = CreateProcessA( NULL, tmp, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, env, NULL, &si, &pi ); + ok( ret, "Couldn't create child process %s\n", tmp ); + winetest_wait_child_process( pi.hProcess ); + CloseHandle( pi.hProcess ); + CloseHandle( pi.hThread ); + free( env ); +} + +static void test_case_insensitive(void) +{ + const char *uppercase_env = getenv("APPDATA"); + const char *lowercase_env = getenv("appdata"); + const wchar_t *uppercase_wenv = _wgetenv(L"APPDATA"); + const wchar_t *lowercase_wenv = _wgetenv(L"appdata"); + + ok( uppercase_env == lowercase_env, "getenv() must be case insensitive, %p should be %p\n", + lowercase_env, uppercase_env ); + ok( uppercase_wenv == lowercase_wenv, "_wgetenv() must be case insensitive, %p should be %p\n", + lowercase_wenv, uppercase_wenv ); + + ok( !_putenv("cAt=bar"), "Failed to set CAT=bar\n" ); + ok( !_putenv("CAT=BAR"), "Failed to set CAT=BAR\n" ); + ok( !strcmp(getenv("cAt"), "BAR"), "_putenv() must be case insensitive\n" ); + + ok( !_wputenv(L"cAt=bar"), "Failed to set CAT=bar\n" ); + ok( !_wputenv(L"CAT=BAR"), "Failed to set CAT=BAR\n" ); + ok( !wcscmp(_wgetenv(L"cAt"), L"BAR"), "_wputenv() must be case insensitive\n" ); + + _putenv("cat="); } START_TEST(environ) { + char **argv; + int argc; + init(); - /* The environ tests should always be run first, as they assume - * that the process has not manipulated the environment. */ + argc = winetest_get_mainargs( &argv ); + if (argc == 3 && !strcmp( argv[2], "create" )) + { + ok( getenv( "__winetest_dog" ) && !strcmp( getenv( "__winetest_dog" ), "bark" ), + "Couldn't find env var\n" ); + ok( _wgetenv( L"__winetest_\u263a" ) && !wcscmp( _wgetenv( L"__winetest_\u263a" ), L"\u03b2" ), + "Couldn't find unicode env var\n" ); + return; + } + test__environ(); test__wenviron(); test_environment_manipulation(); + test_child_env(argv); test_system(); + test_case_insensitive(); } diff --git a/modules/rostests/winetests/msvcrt/file.c b/modules/rostests/winetests/msvcrt/file.c index fe62d5c385e..d082bb269c6 100644 --- a/modules/rostests/winetests/msvcrt/file.c +++ b/modules/rostests/winetests/msvcrt/file.c @@ -35,6 +35,25 @@ #include <process.h> #include <errno.h> #include <locale.h> +#ifdef __REACTOS__ +#include <ntndk.h> +#else +#include <winternl.h> +#endif + +#define WX_OPEN 0x01 +#define WX_ATEOF 0x02 +#define WX_READNL 0x04 +#define WX_PIPE 0x08 +#define WX_DONTINHERIT 0x10 +#define WX_APPEND 0x20 +#define WX_TTY 0x40 +#define WX_TEXT 0x80 + +#define EF_UTF8 0x01 +#define EF_UTF16 0x02 +#define EF_CRIT_INIT 0x04 +#define EF_UNK_UNICODE 0x08 #define MSVCRT_FD_BLOCK_SIZE 32 typedef struct { @@ -52,6 +71,7 @@ static int (__cdecl *p_fopen_s)(FILE**, const char*, const char*); static int (__cdecl *p__wfopen_s)(FILE**, const wchar_t*, const wchar_t*); static errno_t (__cdecl *p__get_fmode)(int*); static errno_t (__cdecl *p__set_fmode)(int); +static int (__cdecl *p__setmaxstdio)(int); static const char* get_base_name(const char *path) { @@ -76,6 +96,7 @@ static void init(void) __pioinfo = (void*)GetProcAddress(hmod, "__pioinfo"); p__get_fmode = (void*)GetProcAddress(hmod, "_get_fmode"); p__set_fmode = (void*)GetProcAddress(hmod, "_set_fmode"); + p__setmaxstdio = (void*)GetProcAddress(hmod, "_setmaxstdio"); } static void test_filbuf( void ) @@ -211,7 +232,50 @@ static void test_fileops( void ) ok(fread(buffer, sizeof(buffer), 1, file) == 0, "fread test failed\n"); /* feof should be set now */ ok(feof(file), "feof after fread failed\n"); - fclose (file); + clearerr(file); + ok(!feof(file), "feof after clearerr failed\n"); + fclose(file); + + file = fopen("fdopen.tst", "rb"); + ok( file != NULL, "fopen failed\n"); + /* sizeof(buffer) > content of file */ + ok(fread(buffer, sizeof(buffer), 1, file) == 0, "fread test failed\n"); + /* feof should be set now */ + ok(feof(file), "feof after fread failed\n"); + rewind(file); + ok(!feof(file), "feof after rewind failed\n"); + fclose(file); + + file = fopen("fdopen.tst", "rb"); + ok( file != NULL, "fopen failed\n"); + /* sizeof(buffer) > content of file */ + ok(fread(buffer, sizeof(buffer), 1, file) == 0, "fread test failed\n"); + /* feof should be set now */ + ok(feof(file), "feof after fread failed\n"); + fseek(file, 0, SEEK_SET); + ok(!feof(file), "feof after fseek failed\n"); + fclose(file); + + file = fopen("fdopen.tst", "rb"); + ok( file != NULL, "fopen failed\n"); + /* sizeof(buffer) > content of file */ + ok(fread(buffer, sizeof(buffer), 1, file) == 0, "fread test failed\n"); + /* feof should be set now */ + ok(feof(file), "feof after fread failed\n"); + fgetpos(file, &pos); + fsetpos(file, &pos); + ok(!feof(file), "feof after fsetpos failed\n"); + fclose(file); + + file = fopen("fdopen.tst", "rb"); + ok( file != NULL, "fopen failed\n"); + /* sizeof(buffer) > content of file */ + ok(fread(buffer, sizeof(buffer), 1, file) == 0, "fread test failed\n"); + /* feof should be set now */ + ok(feof(file), "feof after fread failed\n"); + fsetpos(file, &pos); + ok(!feof(file), "feof after fsetpos failed\n"); + fclose(file); unlink ("fdopen.tst"); } @@ -233,7 +297,7 @@ static void test_readmode( BOOL ascii_mode ) fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE); /* an internal buffer of BUFSIZ is maintained, so make a file big - * enough to test operations that cross the buffer boundary + * enough to test operations that cross the buffer boundary */ j = (2*BUFSIZ-4)/strlen(padbuffer); for (i=0; i<j; i++) @@ -243,8 +307,21 @@ static void test_readmode( BOOL ascii_mode ) write (fd, &padbuffer[i], 1); write (fd, nlbuffer, strlen(nlbuffer)); write (fd, outbuffer, sizeof (outbuffer)); + + errno = 0xdeadbeef; + _doserrno = 0xdeadbeef; + ok(read(fd, buffer, 1) == -1, "read succeeded on write-only file\n"); + ok(errno == EBADF, "errno = %d\n", errno); + ok(_doserrno == ERROR_ACCESS_DENIED, "doserrno = %ld\n", _doserrno); + close (fd); - + + fd = open ("fdopen.tst", O_RDONLY, _S_IREAD |_S_IWRITE); + errno = 0xdeadbeef; + ok(dup2(fd, -1) == -1, "dup2(fd, -1) succeeded\n"); + ok(errno == EBADF, "errno = %d\n", errno); + close (fd); + if (ascii_mode) { /* Open file in ascii mode */ fd = open ("fdopen.tst", O_RDONLY); @@ -256,13 +333,13 @@ static void test_readmode( BOOL ascii_mode ) file = fdopen (fd, "rb"); ao = 0; } - + /* first is a test of fgets, ftell, fseek */ ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE); ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE); l = ftell(file); pl = 2*BUFSIZ-2; - ok(l == pl,"padding line ftell got %d should be %d in %s\n", l, pl, IOMODE); + ok(l == pl,"padding line ftell got %ld should be %d in %s\n", l, pl, IOMODE); ok(lstrlenA(buffer) == pl+ao,"padding line fgets got size %d should be %d in %s\n", lstrlenA(buffer), pl+ao, IOMODE); for (fp=0; fp<strlen(outbuffer); fp++) @@ -270,26 +347,32 @@ static void test_readmode( BOOL ascii_mode ) fp++; ok(fgets(buffer,256,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE); l = ftell(file); - ok(l == pl+fp,"line 1 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE); + ok(l == pl+fp,"line 1 ftell got %ld should be %d in %s\n", l, pl+fp, IOMODE); ok(lstrlenA(buffer) == fp+ao,"line 1 fgets got size %d should be %d in %s\n", lstrlenA(buffer), fp+ao, IOMODE); /* test a seek back across the buffer boundary */ l = pl; ok(fseek(file,l,SEEK_SET)==0,"seek failure in %s\n", IOMODE); l = ftell(file); - ok(l == pl,"ftell after seek got %d should be %d in %s\n", l, pl, IOMODE); + ok(l == pl,"ftell after seek got %ld should be %d in %s\n", l, pl, IOMODE); ok(fgets(buffer,256,file) !=0,"second read of line 1 fgets failed unexpected in %s\n", IOMODE); l = ftell(file); - ok(l == pl+fp,"second read of line 1 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE); + ok(l == pl+fp,"second read of line 1 ftell got %ld should be %d in %s\n", l, pl+fp, IOMODE); ok(lstrlenA(buffer) == fp+ao,"second read of line 1 fgets got size %d should be %d in %s\n", lstrlenA(buffer), fp+ao, IOMODE); ok(fgets(buffer,256,file) !=0,"line 2 fgets failed unexpected in %s\n", IOMODE); fp += 2; l = ftell(file); - ok(l == pl+fp,"line 2 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE); + ok(l == pl+fp,"line 2 ftell got %ld should be %d in %s\n", l, pl+fp, IOMODE); ok(lstrlenA(buffer) == 2+ao,"line 2 fgets got size %d should be %d in %s\n", lstrlenA(buffer), 2+ao, IOMODE); - + + errno = 0xdeadbeef; + _doserrno = 0xdeadbeef; + ok(write(fd, buffer, 1) == -1, "read succeeded on write-only file\n"); + ok(errno == EBADF, "errno = %d\n", errno); + ok(_doserrno == ERROR_ACCESS_DENIED, "doserrno = %ld\n", _doserrno); + /* test fread across buffer boundary */ rewind(file); ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE); @@ -298,7 +381,7 @@ static void test_readmode( BOOL ascii_mode ) i=fread(buffer,1,BUFSIZ+strlen(outbuffer),file); ok(i==BUFSIZ+j,"fread failed, expected %d got %d in %s\n", BUFSIZ+j, i, IOMODE); l = ftell(file); - ok(l == pl+j-(ao*4)-5,"ftell after fread got %d should be %d in %s\n", l, pl+j-(ao*4)-5, IOMODE); + ok(l == pl+j-(ao*4)-5,"ftell after fread got %ld should be %d in %s\n", l, pl+j-(ao*4)-5, IOMODE); for (m=0; m<3; m++) ok(buffer[m]==padbuffer[m+(BUFSIZ-4)%strlen(padbuffer)],"expected %c got %c\n", padbuffer[m], buffer[m]); m+=BUFSIZ+2+ao; @@ -687,7 +770,7 @@ static void test_fflush( void ) char buf1[16], buf2[24]; char *tempf; FILE *tempfh; - int ret; + int ret, fd; tempf=_tempnam(".","wne"); @@ -728,7 +811,23 @@ static void test_fflush( void ) ok(memcmp(buf1, buf2, sizeof(buf1)) == 0, "Got unexpected data (%c)\n", buf2[0]); fclose(tempfh); + unlink(tempf); + + /* test flush failure */ + tempfh = fopen(tempf,"wb"); + ok(tempfh != NULL, "Can't open test file.\n"); + fwrite(obuf, 1, sizeof(obuf), tempfh); + fd = tempfh->_file; + tempfh->_file = -1; + ok(tempfh->_ptr - tempfh->_base, "buffer is empty\n"); + ret = fflush(tempfh); + ok(ret == EOF, "expected EOF, got %d\n", ret); + ok(!(tempfh->_ptr - tempfh->_base), "buffer should be empty\n"); + ok(!tempfh->_cnt, "tempfh->_cnt = %d\n", tempfh->_cnt); + + tempfh->_file = fd; + fclose(tempfh); unlink(tempf); free(tempf); } @@ -764,10 +863,10 @@ static void test_fgetwc( void ) tempfh = fopen(tempf,"rt"); /* open in TEXT mode */ fgetws(wtextW,LLEN,tempfh); l=ftell(tempfh); - ok(l==BUFSIZ-2, "ftell expected %d got %d\n", BUFSIZ-2, l); + ok(l==BUFSIZ-2, "ftell expected %d got %ld\n", BUFSIZ-2, l); fgetws(wtextW,LLEN,tempfh); l=ftell(tempfh); - ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %d\n", BUFSIZ-2+lstrlenA(mytext), l); + ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %ld\n", BUFSIZ-2+lstrlenA(mytext), l); mytextW = AtoW (mytext); aptr = mytextW; wptr = wtextW; @@ -779,7 +878,7 @@ static void test_fgetwc( void ) ok(*wptr == '\n', "Carriage return was not skipped\n"); fclose(tempfh); unlink(tempf); - + tempfh = fopen(tempf,"wb"); j = 'a'; /* pad to almost the length of the internal buffer. Use an odd number of bytes @@ -800,25 +899,25 @@ static void test_fgetwc( void ) fgetws(wtextW,j,tempfh); l=ftell(tempfh); j=(j-1)*sizeof(WCHAR); - ok(l==j, "ftell expected %d got %d\n", j, l); + ok(l==j, "ftell expected %d got %ld\n", j, l); i=fgetc(tempfh); ok(i=='a', "fgetc expected %d got %d\n", 0x61, i); l=ftell(tempfh); j++; - ok(l==j, "ftell expected %d got %d\n", j, l); + ok(l==j, "ftell expected %d got %ld\n", j, l); fgetws(wtextW,3,tempfh); ok(wtextW[0]=='\r',"expected carriage return got %04hx\n", wtextW[0]); ok(wtextW[1]=='\n',"expected newline got %04hx\n", wtextW[1]); l=ftell(tempfh); j += 4; - ok(l==j, "ftell expected %d got %d\n", j, l); + ok(l==j, "ftell expected %d got %ld\n", j, l); for(i=0; i<strlen(mytext); i++) wtextW[i] = 0; /* the first time we get the string, it should be entirely within the local buffer */ fgetws(wtextW,LLEN,tempfh); l=ftell(tempfh); j += (strlen(mytext)-1)*sizeof(WCHAR); - ok(l==j, "ftell expected %d got %d\n", j, l); + ok(l==j, "ftell expected %d got %ld\n", j, l); diff_found = FALSE; aptr = mytextW; wptr = wtextW; @@ -955,6 +1054,38 @@ static void test_fgetwc_unicode(void) ok(ch == WEOF, "got %04hx, expected WEOF (unicode)\n", ch); fclose(tempfh); + tempfh = fopen(tempfile, "r,ccs=utf-8"); + ok(tempfh != NULL, "can't open tempfile\n"); + for (i = 1; i < ARRAY_SIZE(wchar_text); i++) + { + ch = fgetwc(tempfh); + ok(ch == wchar_text[i], + "got %04hx, expected %04x (unicode[%d])\n", ch, wchar_text[i], i-1); + } + ch = fgetwc(tempfh); + ok(ch == WEOF, "got %04hx, expected WEOF (unicode)\n", ch); + fclose(tempfh); + + tempfh = fopen(tempfile, "a,ccs=utf-16le"); + ok(tempfh != NULL, "can't open tempfile\n"); + ch = fputwc('a', tempfh); + ok(ch == 'a', "fputwc returned %x\n", ch); + fclose(tempfh); + + tempfh = fopen(tempfile, "a+,ccs=utf-8"); + ok(tempfh != NULL, "can't open tempfile\n"); + for (i = 1; i < ARRAY_SIZE(wchar_text); i++) + { + ch = fgetwc(tempfh); + ok(ch == wchar_text[i], + "got %04hx, expected %04x (unicode[%d])\n", ch, wchar_text[i], i-1); + } + ch = fgetwc(tempfh); + ok(ch == 'a', "got %04x, expected 'a'\n", ch); + ch = fgetwc(tempfh); + ok(ch == WEOF, "got %04hx, expected WEOF (unicode)\n", ch); + fclose(tempfh); + tempfh = fopen(tempfile, "wb"); ok(tempfh != NULL, "can't open tempfile\n"); ret = WideCharToMultiByte(CP_UTF8, 0, wchar_text, ARRAY_SIZE(wchar_text), @@ -974,6 +1105,57 @@ static void test_fgetwc_unicode(void) ch = fgetwc(tempfh); ok(ch == WEOF, "got %04hx, expected WEOF (utf8)\n", ch); fclose(tempfh); + + tempfh = fopen(tempfile, "wb"); + ok(tempfh != NULL, "can't open tempfile\n"); + fwrite(wchar_text+1, 1, sizeof(wchar_text)-1, tempfh); + fclose(tempfh); + + tempfh = fopen(tempfile, "rt,ccs=utf-16le"); + ok(tempfh != NULL, "can't open tempfile\n"); + for (i = 1; i < ARRAY_SIZE(wchar_text); i++) + { + ch = fgetwc(tempfh); + ok(ch == wchar_text[i], + "got %04hx, expected %04x (unicode[%d])\n", ch, wchar_text[i], i-1); + } + ch = fgetwc(tempfh); + ok(ch == WEOF, "got %04hx, expected WEOF (unicode)\n", ch); + fclose(tempfh); + + tempfh = fopen(tempfile, "wb"); + ok(tempfh != NULL, "can't open tempfile\n"); + ret = WideCharToMultiByte(CP_UTF8, 0, wchar_text + 1, ARRAY_SIZE(wchar_text) - 1, + utf8_text, sizeof(utf8_text), NULL, NULL); + ok(ret > 0, "utf-8 conversion failed\n"); + utf8_text[ret] = 0; + fwrite(utf8_text, sizeof(char), ret, tempfh); + fclose(tempfh); + + tempfh = fopen(tempfile, "rt, ccs=UTF-8"); + ok(tempfh != NULL, "can't open tempfile\n"); + for (i = 1; i < ARRAY_SIZE(wchar_text); i++) + { + ch = fgetwc(tempfh); + ok(ch == wchar_text[i], + "got %04hx, expected %04x (utf8[%d])\n", ch, wchar_text[i], i-1); + } + ch = fgetwc(tempfh); + ok(ch == WEOF, "got %04hx, expected WEOF (utf8)\n", ch); + fclose(tempfh); + + tempfh = fopen(tempfile, "rt, ccs=unicode"); + ok(tempfh != NULL, "can't open tempfile\n"); + for (i = 0; utf8_text[i]; i++) + { + ch = fgetwc(tempfh); + ok(ch == (unsigned char) utf8_text[i], + "got %04hx, expected %04x (unicode[%d])\n", ch, (unsigned char)utf8_text[i], i); + } + ch = fgetwc(tempfh); + ok(ch == WEOF, "got %04hx, expected WEOF (unicode)\n", ch); + fclose(tempfh); + unlink(temppath); } @@ -1034,6 +1216,98 @@ static void test_fputwc(void) _unlink(tempfile); } +static void test_freopen( void ) +{ + char filename1[8] = "AXXXXXX"; + char filename2[8] = "BXXXXXX"; + FILE *file; + FILE *new; + int ret; + int fd; + char ch; + long pos; + + mktemp(filename1); + mktemp(filename2); + + file = fopen(filename1, "wt"); + ok(file != NULL, "fopen(filename1) returned NULL\n"); + ret = fwrite("1", 1, 1, file); + ok(ret == 1, "fwrite() returned %d (%d)\n", ret, errno); + ret = fclose(file); + ok(ret == 0, "fclose() returned %d\n", ret); + + file = fopen(filename2, "wt"); + ok(file != NULL, "fopen(filename1) returned NULL\n"); + ret = fwrite("2", 1, 1, file); + ok(ret == 1, "fwrite() returned %d (%d)\n", ret, errno); + ret = fclose(file); + ok(ret == 0, "fclose() returned %d\n", ret); + + file = fopen(filename1, "rt"); + ok(file != NULL, "fopen(filename1) returned NULL\n"); + file = freopen(filename2, "rt", file); + ok(file != NULL, "fopen(filename2) returned NULL\n"); + ch = '#'; + ret = fread(&ch, 1, 1, file); + ok(ret == 1, "fread() returned %d\n", ret); + ok(ch == '2', "fread() read %c\n", ch); + ret = fclose(file); + ok(ret == 0, "fclose() returned %d\n", ret); + + file = fopen(filename1, "at"); + ok(file != NULL, "fopen(filename1) returned NULL\n"); + file = freopen(filename1, "rt", file); + ok(file != NULL, "fopen(filename1) returned NULL\n"); + pos = ftell(file); + ok(pos == 0, "ftell() returned %ld\n", pos); + ch = '#'; + ret = fread(&ch, 1, 1, file); + ok(ret == 1, "fread() returned %d\n", ret); + ok(ch == '1', "fread() read %c\n", ch); + ret = fclose(file); + ok(ret == 0, "fclose() returned %d\n", ret); + + file = fopen(filename1, "rt"); + ok(file != NULL, "fopen(filename1) returned NULL\n"); + fd = fileno(file); + ok(fd > 0, "fileno() returned %d\n", fd); + /* invalid filename */ + new = freopen("_:", "rt", file); + ok(new == NULL, "fopen(_:) returned non NULL\n"); + errno = 0xdeadbeef; + ch = '#'; + ret = read(fd, &ch, 1); + ok(ret == -1, "read() returned %d\n", ret); + ok(errno == EBADF, "errno is %d\n", errno); + errno = 0xdeadbeef; + ret = fclose(file); + ok(ret == EOF, "fclose(file) succeeded\n"); + ok(errno == 0xdeadbeef, "errno is %d\n", errno); + + file = fopen(filename1, "rb"); + ok(file != NULL, "couldn't open %s\n", filename1); + close(file->_file); + file->_file = -1; + + new = freopen(filename2, "rb", file); + ok(new == file, "freopen() didn't return same FILE*\n"); + + fd = fileno(file); + ok(fd > 0, "fileno() returned %d\n", fd); + + ch = '#'; + ret = fread(&ch, 1, 1, file); + ok(ret == 1, "fread() returned %d\n", ret); + ok(ch == '2', "Unexpected char\n"); + + ret = fclose(file); + ok(ret == 0, "fclose(file) returned %d\n", ret); + + unlink(filename1); + unlink(filename2); +} + static void test_ctrlz( void ) { char* tempf; @@ -1062,17 +1336,17 @@ static void test_ctrlz( void ) ok(i==j, "returned string length expected %d got %d\n", j, i); j+=4; /* ftell should indicate the true end of file */ l=ftell(tempfh); - ok(l==j, "ftell expected %d got %d\n", j, l); + ok(l==j, "ftell expected %d got %ld\n", j, l); ok(feof(tempfh), "did not get EOF\n"); fclose(tempfh); - + tempfh = fopen(tempf,"rb"); /* open in BINARY mode */ ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n"); i=strlen(buffer); j=strlen(mytext)+3; /* should get through newline */ ok(i==j, "returned string length expected %d got %d\n", j, i); l=ftell(tempfh); - ok(l==j, "ftell expected %d got %d\n", j, l); + ok(l==j, "ftell expected %d got %ld\n", j, l); ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n"); i=strlen(buffer); ok(i==1, "returned string length expected %d got %d\n", 1, i); @@ -1185,7 +1459,7 @@ static void test_file_write_read( void ) memset(btext, 0, LLEN); tempfd = _open(tempf,_O_APPEND|_O_RDWR); /* open for APPEND in default mode */ - ok(tell(tempfd) == 0, "bad position %u expecting 0\n", tell(tempfd)); + ok(tell(tempfd) == 0, "bad position %lu expecting 0\n", tell(tempfd)); ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext), "_read _O_APPEND got bad length\n"); ok( memcmp(mytext,btext,strlen(mytext)) == 0, "problems with _O_APPEND _read\n"); _close(tempfd); @@ -1206,15 +1480,15 @@ static void test_file_write_read( void ) _lseek(tempfd, -3, FILE_END); ret = _read(tempfd,btext,1); ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret); - ok(tell(tempfd) == 41, "bad position %u expecting 41\n", tell(tempfd)); + ok(tell(tempfd) == 41, "bad position %lu expecting 41\n", tell(tempfd)); _lseek(tempfd, -3, FILE_END); ret = _read(tempfd,btext,2); ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret); - ok(tell(tempfd) == 42, "bad position %u expecting 42\n", tell(tempfd)); + ok(tell(tempfd) == 42, "bad position %lu expecting 42\n", tell(tempfd)); _lseek(tempfd, -3, FILE_END); ret = _read(tempfd,btext,3); ok(ret == 2 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret); - ok(tell(tempfd) == 43, "bad position %u expecting 43\n", tell(tempfd)); + ok(tell(tempfd) == 43, "bad position %lu expecting 43\n", tell(tempfd)); _close(tempfd); ret = unlink(tempf); @@ -1336,9 +1610,9 @@ static void test_file_write_read( void ) /* test invalid utf8 sequence */ lseek(tempfd, 5, SEEK_SET); ret = _read(tempfd, btext, sizeof(btext)); - todo_wine ok(ret == 10, "_read returned %d, expected 10\n", ret); + ok(ret == 10, "_read returned %d, expected 10\n", ret); /* invalid char should be replaced by U+FFFD in MultiByteToWideChar */ - todo_wine ok(!memcmp(btext, "\xfd\xff", 2), "invalid UTF8 character was not replaced by U+FFFD\n"); + ok(!memcmp(btext, "\xfd\xff", 2), "invalid UTF8 character was not replaced by U+FFFD\n"); ok(!memcmp(btext+ret-8, "\x62\x00\x7c\x01\x0d\x00\x0a\x00", 8), "btext is incorrect\n"); _close(tempfd); } @@ -1355,13 +1629,27 @@ static void test_file_write_read( void ) free(tempf); } -static void test_file_inherit_child(const char* fd_s) +static void test_file_inherit_child(const char* fd_s, const char *handle_str) { + HANDLE handle_value; int fd = atoi(fd_s); + HANDLE *handle_ptr; + unsigned int count; char buffer[32]; + STARTUPINFOA si; int ret; - ret =write(fd, "Success", 8); + GetStartupInfoA(&si); + count = *(unsigned *)si.lpReserved2; + if (handle_str) + { + ok(count == 3, "Got unexpected count %u.\n", count); + sscanf(handle_str, "%p", &handle_value); + handle_ptr = (HANDLE *)(si.lpReserved2 + sizeof(unsigned) + count); + ok(handle_value == handle_ptr[1], "Got unexpected handle %p.\n", handle_ptr[1]); + } + + ret = write(fd, "Success", 8); ok( ret == 8, "Couldn't write in child process on %d (%s)\n", fd, strerror(errno)); lseek(fd, 0, SEEK_SET); ok(read(fd, buffer, sizeof (buffer)) == 8, "Couldn't read back the data\n"); @@ -1374,7 +1662,7 @@ static void test_file_inherit_child_no(const char* fd_s) int ret; ret = write(fd, "Success", 8); - ok( ret == -1 && errno == EBADF, + ok( ret == -1 && errno == EBADF, "Wrong write result in child process on %d (%s)\n", fd, strerror(errno)); } @@ -1430,7 +1718,7 @@ static void test_stdout_handle( STARTUPINFOA *startup, char *cmdline, HANDLE hst CreateProcessA( NULL, cmdline, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, startup, &proc ); - winetest_wait_child_process( proc.hProcess ); + wait_child_process( proc.hProcess ); data = read_file( hErrorFile ); if (expect_stdout) @@ -1451,6 +1739,18 @@ static void test_stdout_handle( STARTUPINFOA *startup, char *cmdline, HANDLE hst DeleteFileA( "fdopen.err" ); } +static unsigned WINAPI read_pipe_thread(void *argument) +{ + unsigned char buffer[2]; + int ret; + int *pipefds = argument; + + ret = _read(pipefds[0], buffer, sizeof(buffer)); + ok(ret == 1, "ret = %d\n", ret); + ok(buffer[0] == 'a', "%x\n", buffer[0]); + return 0; +} + static void test_file_inherit( const char* selfname ) { int fd; @@ -1460,33 +1760,62 @@ static void test_file_inherit( const char* selfname ) STARTUPINFOA startup; SECURITY_ATTRIBUTES sa; HANDLE handles[3]; + HANDLE thread_handle; + int pipefds[2]; + intptr_t ret; fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE); ok(fd != -1, "Couldn't create test file\n"); arg_v[0] = get_base_name(selfname); - arg_v[1] = "tests/file.c"; + arg_v[1] = "file"; arg_v[2] = "inherit"; arg_v[3] = buffer; sprintf(buffer, "%d", fd); arg_v[4] = 0; - _spawnvp(_P_WAIT, selfname, arg_v); - ok(tell(fd) == 8, "bad position %u expecting 8\n", tell(fd)); + ret = _spawnvp(_P_WAIT, selfname, arg_v); + ok(ret == 0, "_spawnvp returned %Id, errno %d\n", ret, errno); + ok(tell(fd) == 8, "bad position %lu expecting 8\n", tell(fd)); lseek(fd, 0, SEEK_SET); ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n"); close (fd); ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n"); - + fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE); ok(fd != -1, "Couldn't create test file\n"); - arg_v[1] = "tests/file.c"; + arg_v[1] = "file"; arg_v[2] = "inherit_no"; arg_v[3] = buffer; sprintf(buffer, "%d", fd); arg_v[4] = 0; - _spawnvp(_P_WAIT, selfname, arg_v); - ok(tell(fd) == 0, "bad position %u expecting 0\n", tell(fd)); + ret = _spawnvp(_P_WAIT, selfname, arg_v); + ok(ret == 0, "_spawnvp returned %Id, errno %d\n", ret, errno); + ok(tell(fd) == 0, "bad position %lu expecting 0\n", tell(fd)); ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer); close (fd); ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n"); + /* Show that spawn works while a read is active */ + ok(_pipe(pipefds, 1, O_BINARY) == 0, "_pipe() failed\n"); + thread_handle = (HANDLE)_beginthreadex(NULL, 0, read_pipe_thread, pipefds, 0, NULL); + Sleep(100); /* try to make sure the thread is reading */ + fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE); + ok(fd != -1, "Couldn't create test file\n"); + arg_v[1] = "tests/file.c"; + arg_v[2] = "inherit"; + arg_v[3] = buffer; sprintf(buffer, "%d", fd); + arg_v[4] = 0; + ret = _spawnvp(_P_WAIT, selfname, arg_v); + ok(ret == 0, "_spawnvp returned %Id, errno %d\n", ret, errno); + ret = tell(fd); + ok(ret == 8, "bad position %Iu expecting 8\n", ret); + lseek(fd, 0, SEEK_SET); + ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n"); + close (fd); + ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n"); + _write(pipefds[1], "a", 1); + WaitForSingleObject(thread_handle, INFINITE); + CloseHandle(thread_handle); + close(pipefds[0]); + close(pipefds[1]); + /* make file handle inheritable */ sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; @@ -1544,6 +1873,22 @@ static void test_file_inherit( const char* selfname ) test_stdout_handle( &startup, cmdline, handles[1], TRUE, "large size block" ); CloseHandle( handles[1] ); DeleteFileA("fdopen.tst"); + + /* test inherit block with invalid handle */ + handles[1] = INVALID_HANDLE_VALUE; + create_io_inherit_block( &startup, 3, handles ); + sprintf(cmdline, "%s file inherit 1 %p", selfname, handles[1]); + test_stdout_handle( &startup, cmdline, NULL, FALSE, "INVALID_HANDLE_VALUE stdout handle" ); + + handles[1] = NULL; + create_io_inherit_block( &startup, 3, handles ); + sprintf(cmdline, "%s file inherit 1 %p", selfname, handles[1]); + test_stdout_handle( &startup, cmdline, NULL, FALSE, "NULL stdout handle" ); + + handles[1] = (void *)0xdeadbeef; + create_io_inherit_block( &startup, 3, handles ); + sprintf(cmdline, "%s file inherit 1 %p", selfname, handles[1]); + test_stdout_handle( &startup, cmdline, NULL, FALSE, "invalid stdout handle" ); } static void test_invalid_stdin_child( void ) @@ -1557,6 +1902,8 @@ static void test_invalid_stdin_child( void ) handle = (HANDLE)_get_osfhandle(STDIN_FILENO); ok(handle == (HANDLE)-2, "handle = %p\n", handle); ok(errno == 0xdeadbeef, "errno = %d\n", errno); + handle = GetStdHandle(STD_INPUT_HANDLE); + ok((LONG_PTR)handle > 0, "Expecting passed handle to be untouched\n"); info = &__pioinfo[STDIN_FILENO/MSVCRT_FD_BLOCK_SIZE][STDIN_FILENO%MSVCRT_FD_BLOCK_SIZE]; ok(info->handle == (HANDLE)-2, "info->handle = %p\n", info->handle); @@ -1631,7 +1978,11 @@ static void test_invalid_stdin( const char* selfname ) } ret = RegOpenCurrentUser(KEY_READ, &key); - ok(!ret, "RegOpenCurrentUser failed: %x\n", ret); + ok(!ret, "RegOpenCurrentUser failed: %lx\n", ret); + + ret = DuplicateHandle(GetCurrentProcess(), key, GetCurrentProcess(), + (HANDLE *)&key, GENERIC_READ, TRUE, DUPLICATE_CLOSE_SOURCE); + ok(ret, "DuplicateHandle failed: %lx\n", GetLastError()); sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; @@ -1647,10 +1998,10 @@ static void test_invalid_stdin( const char* selfname ) sprintf(cmdline, "%s file stdin", selfname); CreateProcessA(NULL, cmdline, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE|NORMAL_PRIORITY_CLASS, NULL, NULL, &startup, &proc); - winetest_wait_child_process(proc.hProcess); + wait_child_process(proc.hProcess); ret = RegCloseKey(key); - ok(!ret, "RegCloseKey failed: %x\n", ret); + ok(!ret, "RegCloseKey failed: %lx\n", ret); } static void test_tmpnam( void ) @@ -1678,8 +2029,8 @@ static void test_chsize( void ) LONG cur, pos, count; char temptext[] = "012345678"; char *tempfile = _tempnam( ".", "tst" ); - - ok( tempfile != NULL, "Couldn't create test file: %s\n", tempfile ); + + ok( tempfile != NULL, "Couldn't create test file\n" ); fd = _open( tempfile, _O_CREAT|_O_TRUNC|_O_RDWR, _S_IREAD|_S_IWRITE ); ok( fd > 0, "Couldn't open test file\n" ); @@ -1694,14 +2045,14 @@ static void test_chsize( void ) ok( _chsize( fd, sizeof(temptext) / 2 ) == 0, "_chsize() failed\n" ); pos = _lseek( fd, 0, SEEK_CUR ); - ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos ); + ok( cur == pos, "File pointer changed from: %ld to: %ld\n", cur, pos ); ok( _filelength( fd ) == sizeof(temptext) / 2, "Wrong file size\n" ); /* enlarge the file */ - ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" ); + ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" ); pos = _lseek( fd, 0, SEEK_CUR ); - ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos ); + ok( cur == pos, "File pointer changed from: %ld to: %ld\n", cur, pos ); ok( _filelength( fd ) == sizeof(temptext) * 2, "Wrong file size\n" ); _close( fd ); @@ -1733,7 +2084,7 @@ static void test_fopen_fclose_fcloseall( void ) "filename is empty, errno = %d (expected 2 or 22)\n", errno); errno = 0xfaceabad; stream4 = fopen(NULL, "w+"); - ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT), + ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT), "filename is NULL, errno = %d (expected 2 or 22)\n", errno); /* testing fclose() */ @@ -1748,6 +2099,9 @@ static void test_fopen_fclose_fcloseall( void ) ret = fclose(stream3); ok(ret == EOF, "Closing file '%s' returned %d\n", fname3, ret); ok(errno == 0xdeadbeef, "errno = %d\n", errno); + ret = fclose(NULL); + ok(ret == EOF, "Closing NULL file returned %d\n", ret); + ok(errno == EINVAL, "errno = %d\n", errno); /* testing fcloseall() */ numclosed = _fcloseall(); @@ -1879,12 +2233,6 @@ static void test_fopen_s( void ) static void test__wfopen_s( void ) { const char name[] = "empty1"; - const WCHAR wname[] = { - 'e','m','p','t','y','1',0 - }; - const WCHAR wmode[] = { - 'w',0 - }; char buff[16]; FILE *file; int ret; @@ -1896,7 +2244,7 @@ static void test__wfopen_s( void ) return; } /* testing _wfopen_s */ - ret = p__wfopen_s(&file, wname, wmode); + ret = p__wfopen_s(&file, L"empty1", L"w"); ok(ret == 0, "_wfopen_s failed with %d\n", ret); ok(file != 0, "_wfopen_s failed to return value\n"); fwrite(name, sizeof(name), 1, file); @@ -2007,8 +2355,12 @@ static void test_get_osfhandle(void) static void test_setmaxstdio(void) { - ok(2048 == _setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",_setmaxstdio(2048)); - ok(-1 == _setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",_setmaxstdio(2049)); + if (p__setmaxstdio) + { + ok(2048 == p__setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",p__setmaxstdio(2048)); + ok(-1 == p__setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",p__setmaxstdio(2049)); + } + else win_skip( "_setmaxstdio not supported\n" ); } static void test_stat(void) @@ -2168,7 +2520,7 @@ static void test_pipes(const char* selfname) } arg_v[0] = get_base_name(selfname); - arg_v[1] = "tests/file.c"; + arg_v[1] = "file"; arg_v[2] = "pipes"; arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]); arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]); @@ -2197,7 +2549,7 @@ static void test_pipes(const char* selfname) return; } - arg_v[1] = "tests/file.c"; + arg_v[1] = "file"; arg_v[2] = "pipes"; arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]); arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]); @@ -2313,7 +2665,7 @@ static void test_stdin(void) "GetStdHandle(STD_INPUT_HANDLE) != _get_osfhandle(STDIN_FILENO)\n"); r = SetStdHandle(STD_INPUT_HANDLE, INVALID_HANDLE_VALUE); - ok(r == TRUE, "SetStdHandle returned %x, expected TRUE\n", r); + ok(r == TRUE, "SetStdHandle returned %lx, expected TRUE\n", r); h = GetStdHandle(STD_INPUT_HANDLE); ok(h == INVALID_HANDLE_VALUE, "h = %p\n", h); @@ -2548,7 +2900,7 @@ static void test__creat(void) pos = _tell(fd); ok(pos == 6, "expected pos 6 (text mode), got %d\n", pos); } - ok(_lseek(fd, SEEK_SET, 0) == 0, "_lseek failed\n"); + ok(_lseek(fd, 0, SEEK_SET) == 0, "_lseek failed\n"); count = _read(fd, buf, 6); ok(count == 4, "_read returned %d, expected 4\n", count); count = count > 0 ? count > 4 ? 4 : count : 0; @@ -2568,7 +2920,7 @@ static void test__creat(void) pos = _tell(fd); ok(pos == 4, "expected pos 4 (binary mode), got %d\n", pos); } - ok(_lseek(fd, SEEK_SET, 0) == 0, "_lseek failed\n"); + ok(_lseek(fd, 0, SEEK_SET) == 0, "_lseek failed\n"); count = _read(fd, buf, 6); ok(count == 4, "_read returned %d, expected 4\n", count); count = count > 0 ? count > 4 ? 4 : count : 0; @@ -2583,6 +2935,215 @@ static void test__creat(void) p__set_fmode(old_fmode); } +static void test_lseek(void) +{ + int fd; + char testdata[4] = {'a', '\n', 'b', '\n'}; + + errno = 0xdeadbeef; + ok(_lseek(-42, 0, SEEK_SET) == -1, "expected failure\n"); + ok(errno == EBADF, "errno = %d\n", errno); + + fd = _creat("_creat.tst", _S_IWRITE); + ok(fd > 0, "_creat failed\n"); + _write(fd, testdata, 4); + + errno = 0xdeadbeef; + ok(_lseek(fd, 0, 42) == -1, "expected failure\n"); + ok(errno == EINVAL, "errno = %d\n", errno); + + errno = 0xdeadbeef; + ok(_lseek(fd, -42, SEEK_SET) == -1, "expected failure\n"); + ok(errno == EINVAL, "errno = %d\n", errno); + + _close(fd); + DeleteFileA("_creat.tst"); +} + +static BOOL has_sequential_hint(int fd) +{ + HANDLE handle; + FILE_MODE_INFORMATION mode_info; + IO_STATUS_BLOCK io; + NTSTATUS status; + + handle = (HANDLE)_get_osfhandle(fd); + status = NtQueryInformationFile(handle, &io, &mode_info, sizeof(mode_info), + FileModeInformation); + ok(!status, "NtQueryInformationFile failed\n"); + return (mode_info.Mode & FILE_SEQUENTIAL_ONLY) != 0; +} + +static void test_fopen_hints(void) +{ + static const struct { + const char *mode; + BOOL seq; + } tests[] = { + { "rb", FALSE }, + { "rbS", TRUE }, + { "rbR", FALSE }, + { "rbSR", TRUE }, + { "rbRS", FALSE } + }; + + char temppath[MAX_PATH], tempfile[MAX_PATH]; + FILE *fp; + int i; + + GetTempPathA(MAX_PATH, temppath); + GetTempFileNameA(temppath, "", 0, tempfile); + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + fp = fopen(tempfile, tests[i].mode); + ok(fp != NULL, "unable to fopen test file with mode \"%s\"\n", tests[i].mode); + ok(has_sequential_hint(_fileno(fp)) == tests[i].seq, + "unexpected sequential hint for fopen mode \"%s\"\n", tests[i].mode); + fclose(fp); + } + unlink(tempfile); +} + +static void test_open_hints(void) +{ + static const struct { + int mode; + BOOL seq; + } tests[] = { + { _O_RDONLY | _O_BINARY, FALSE }, + { _O_RDONLY | _O_BINARY | _O_SEQUENTIAL, TRUE }, + { _O_RDONLY | _O_BINARY | _O_RANDOM, FALSE }, + { _O_RDONLY | _O_BINARY | _O_RANDOM | _O_SEQUENTIAL, TRUE } + }; + + char temppath[MAX_PATH], tempfile[MAX_PATH]; + int fd; + int i; + + GetTempPathA(MAX_PATH, temppath); + GetTempFileNameA(temppath, "", 0, tempfile); + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + fd = open(tempfile, tests[i].mode); + ok(fd != -1, "unable to _open test file with flags %x\n", tests[i].mode); + ok(has_sequential_hint(fd) == tests[i].seq, + "unexpected sequential hint for _open flags %x\n", tests[i].mode); + close(fd); + } + unlink(tempfile); +} + +static void test_ioinfo_flags(void) +{ + HANDLE handle; + ioinfo *info; + char *tempf; + int tempfd; + + tempf = _tempnam(".","wne"); + + tempfd = _open(tempf, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_WTEXT, _S_IWRITE); + ok(tempfd != -1, "_open failed with error: %d\n", errno); + + handle = (HANDLE)_get_osfhandle(tempfd); + info = &__pioinfo[tempfd / MSVCRT_FD_BLOCK_SIZE][tempfd % MSVCRT_FD_BLOCK_SIZE]; + ok(!!info, "NULL info.\n"); + ok(info->handle == handle, "Unexpected handle %p, expected %p.\n", info->handle, handle); + ok(info->exflag == (EF_UTF16 | EF_CRIT_INIT | EF_UNK_UNICODE), "Unexpected exflag %#x.\n", info->exflag); + ok(info->wxflag == (WX_TEXT | WX_OPEN), "Unexpected wxflag %#x.\n", info->wxflag); + + close(tempfd); + + ok(info->handle == INVALID_HANDLE_VALUE, "Unexpected handle %p.\n", info->handle); + ok(info->exflag == (EF_UTF16 | EF_CRIT_INIT | EF_UNK_UNICODE), "Unexpected exflag %#x.\n", info->exflag); + ok(!info->wxflag, "Unexpected wxflag %#x.\n", info->wxflag); + + info = &__pioinfo[(tempfd + 4) / MSVCRT_FD_BLOCK_SIZE][(tempfd + 4) % MSVCRT_FD_BLOCK_SIZE]; + ok(!!info, "NULL info.\n"); + ok(info->handle == INVALID_HANDLE_VALUE, "Unexpected handle %p.\n", info->handle); + ok(!info->exflag, "Unexpected exflag %#x.\n", info->exflag); + + unlink(tempf); + free(tempf); +} + +static void test_std_stream_buffering(void) +{ + int dup_fd, ret, pos; + FILE *file; + char ch; + + dup_fd = _dup(STDOUT_FILENO); + ok(dup_fd != -1, "_dup failed\n"); + + file = freopen("std_stream_test.tmp", "w", stdout); + ok(file != NULL, "freopen failed\n"); + + ret = fprintf(stdout, "test"); + pos = _telli64(STDOUT_FILENO); + + fflush(stdout); + _dup2(dup_fd, STDOUT_FILENO); + close(dup_fd); + setvbuf(stdout, NULL, _IONBF, 0); + + ok(ret == 4, "fprintf(stdout) returned %d\n", ret); + ok(!pos, "expected stdout to be buffered\n"); + + dup_fd = _dup(STDERR_FILENO); + ok(dup_fd != -1, "_dup failed\n"); + + file = freopen("std_stream_test.tmp", "w", stderr); + ok(file != NULL, "freopen failed\n"); + + ret = fprintf(stderr, "test"); + ok(ret == 4, "fprintf(stderr) returned %d\n", ret); + pos = _telli64(STDERR_FILENO); + ok(!pos, "expected stderr to be buffered\n"); + + fflush(stderr); + _dup2(dup_fd, STDERR_FILENO); + close(dup_fd); + + dup_fd = _dup(STDIN_FILENO); + ok(dup_fd != -1, "_dup failed\n"); + + file = freopen("std_stream_test.tmp", "r", stdin); + ok(file != NULL, "freopen failed\n"); + + ch = 0; + ret = fscanf(stdin, "%c", &ch); + ok(ret == 1, "fscanf returned %d\n", ret); + ok(ch == 't', "ch = 0x%x\n", (unsigned char)ch); + pos = _telli64(STDIN_FILENO); + ok(pos == 4, "pos = %d\n", pos); + + fflush(stdin); + _dup2(dup_fd, STDIN_FILENO); + close(dup_fd); + + ok(DeleteFileA("std_stream_test.tmp"), "DeleteFile failed\n"); +} + +static void test_std_stream_open(void) +{ + FILE *f; + int fd; + + fd = _dup(STDIN_FILENO); + ok(fd != -1, "_dup failed\n"); + + ok(!fclose(stdin), "fclose failed\n"); + f = fopen("nul", "r"); + ok(f == stdin, "f = %p, expected %p\n", f, stdin); + ok(_fileno(f) == STDIN_FILENO, "_fileno(f) = %d\n", _fileno(f)); + + _dup2(fd, STDIN_FILENO); + close(fd); +} + START_TEST(file) { int arg_c; @@ -2596,7 +3157,7 @@ START_TEST(file) if (arg_c >= 3) { if (strcmp(arg_v[2], "inherit") == 0) - test_file_inherit_child(arg_v[3]); + test_file_inherit_child(arg_v[3], arg_c > 4 ? arg_v[4] : NULL); else if (strcmp(arg_v[2], "inherit_no") == 0) test_file_inherit_child_no(arg_v[3]); else if (strcmp(arg_v[2], "pipes") == 0) @@ -2642,6 +3203,7 @@ START_TEST(file) test_fgetwc_locale("AB\x83\xa9", "C", 0); test_fgetwc_unicode(); test_fputwc(); + test_freopen(); test_ctrlz(); test_file_put_get(); test_tmpnam(); @@ -2654,6 +3216,12 @@ START_TEST(file) test_write_flush(); test_close(); test__creat(); + test_lseek(); + test_fopen_hints(); + test_open_hints(); + test_ioinfo_flags(); + test_std_stream_buffering(); + test_std_stream_open(); /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report * file contains lines in the correct order diff --git a/modules/rostests/winetests/msvcrt/heap.c b/modules/rostests/winetests/msvcrt/heap.c index d934bf0c542..e8da95bb867 100644 --- a/modules/rostests/winetests/msvcrt/heap.c +++ b/modules/rostests/winetests/msvcrt/heap.c @@ -23,17 +23,13 @@ #include <errno.h> #include "wine/test.h" -#ifdef __REACTOS__ -#if defined(__GNUC__) && __GNUC__ >= 7 -#pragma GCC diagnostic ignored "-Walloc-size-larger-than=9223372036854775807" -#endif -#endif - -static void (__cdecl *p_aligned_free)(void*) = NULL; -static void * (__cdecl *p_aligned_malloc)(size_t,size_t) = NULL; -static void * (__cdecl *p_aligned_offset_malloc)(size_t,size_t,size_t) = NULL; -static void * (__cdecl *p_aligned_realloc)(void*,size_t,size_t) = NULL; -static void * (__cdecl *p_aligned_offset_realloc)(void*,size_t,size_t,size_t) = NULL; +static void (__cdecl *p_aligned_free)(void*); +static void * (__cdecl *p_aligned_malloc)(size_t,size_t); +static void * (__cdecl *p_aligned_offset_malloc)(size_t,size_t,size_t); +static void * (__cdecl *p_aligned_realloc)(void*,size_t,size_t); +static void * (__cdecl *p_aligned_offset_realloc)(void*,size_t,size_t,size_t); +static int (__cdecl *p__set_sbh_threshold)(size_t); +static size_t (__cdecl *p__get_sbh_threshold)(void); static void test_aligned_malloc(unsigned int size, unsigned int alignment) { @@ -421,28 +417,37 @@ static void test_aligned(void) static void test_sbheap(void) { + HMODULE msvcrt = GetModuleHandleA("msvcrt.dll"); void *mem; int threshold; + p__set_sbh_threshold = (void*)GetProcAddress(msvcrt, "_set_sbh_threshold"); + p__get_sbh_threshold = (void*)GetProcAddress(msvcrt, "_get_sbh_threshold"); + if (!p__set_sbh_threshold || !p__get_sbh_threshold) + { + win_skip("_set_sbh_threshold not available\n"); + return; + } + if(sizeof(void*) == 8) { - ok(!_set_sbh_threshold(0), "_set_sbh_threshold succeeded\n"); - ok(!_set_sbh_threshold(1000), "_set_sbh_threshold succeeded\n"); + ok(!p__set_sbh_threshold(0), "_set_sbh_threshold succeeded\n"); + ok(!p__set_sbh_threshold(1000), "_set_sbh_threshold succeeded\n"); return; } mem = malloc(1); ok(mem != NULL, "malloc failed\n"); - ok(_set_sbh_threshold(1), "_set_sbh_threshold failed\n"); - threshold = _get_sbh_threshold(); + ok(p__set_sbh_threshold(1), "_set_sbh_threshold failed\n"); + threshold = p__get_sbh_threshold(); ok(threshold == 16, "threshold = %d\n", threshold); - ok(_set_sbh_threshold(8), "_set_sbh_threshold failed\n"); - threshold = _get_sbh_threshold(); + ok(p__set_sbh_threshold(8), "_set_sbh_threshold failed\n"); + threshold = p__get_sbh_threshold(); ok(threshold == 16, "threshold = %d\n", threshold); - ok(_set_sbh_threshold(1000), "_set_sbh_threshold failed\n"); - threshold = _get_sbh_threshold(); + ok(p__set_sbh_threshold(1000), "_set_sbh_threshold failed\n"); + threshold = p__get_sbh_threshold(); ok(threshold == 1008, "threshold = %d\n", threshold); free(mem); @@ -455,13 +460,42 @@ static void test_sbheap(void) ok(mem != NULL, "realloc failed\n"); ok(!((UINT_PTR)mem & 0xf), "incorrect alignment (%p)\n", mem); - ok(_set_sbh_threshold(0), "_set_sbh_threshold failed\n"); - threshold = _get_sbh_threshold(); + ok(p__set_sbh_threshold(0), "_set_sbh_threshold failed\n"); + threshold = p__get_sbh_threshold(); ok(threshold == 0, "threshold = %d\n", threshold); free(mem); } +static void test_malloc(void) +{ + /* use function pointers to bypass gcc builtins */ + void *(__cdecl *p_malloc)(size_t); + void *(__cdecl *p_realloc)(void *,size_t); + void *mem; + + p_malloc = (void *)GetProcAddress( GetModuleHandleA("msvcrt.dll"), "malloc"); + p_realloc = (void *)GetProcAddress( GetModuleHandleA("msvcrt.dll"), "realloc"); + + mem = p_malloc(0); + ok(mem != NULL, "memory not allocated for size 0\n"); + free(mem); + + mem = p_realloc(NULL, 10); + ok(mem != NULL, "memory not allocated\n"); + + mem = p_realloc(mem, 20); + ok(mem != NULL, "memory not reallocated\n"); + + mem = p_realloc(mem, 0); + ok(mem == NULL, "memory not freed\n"); + + mem = p_realloc(NULL, 0); + ok(mem != NULL, "memory not (re)allocated for size 0\n"); + + free(mem); +} + static void test_calloc(void) { /* use function pointer to bypass gcc builtin */ @@ -489,29 +523,16 @@ static void test_calloc(void) free(ptr); } -START_TEST(heap) +static void test__get_heap_handle(void) { - void *mem; - - mem = malloc(0); - ok(mem != NULL, "memory not allocated for size 0\n"); - free(mem); - - mem = realloc(NULL, 10); - ok(mem != NULL, "memory not allocated\n"); - - mem = realloc(mem, 20); - ok(mem != NULL, "memory not reallocated\n"); - - mem = realloc(mem, 0); - ok(mem == NULL, "memory not freed\n"); - - mem = realloc(NULL, 0); - ok(mem != NULL, "memory not (re)allocated for size 0\n"); - - free(mem); + ok((HANDLE)_get_heap_handle() != GetProcessHeap(), "Expected _get_heap_handle() not to return GetProcessHeap()\n"); +} +START_TEST(heap) +{ test_aligned(); test_sbheap(); + test_malloc(); test_calloc(); + test__get_heap_handle(); } diff --git a/modules/rostests/winetests/msvcrt/locale.c b/modules/rostests/winetests/msvcrt/locale.c index 08abac00bed..62632ce4b9d 100644 --- a/modules/rostests/winetests/msvcrt/locale.c +++ b/modules/rostests/winetests/msvcrt/locale.c @@ -19,6 +19,7 @@ */ #include <locale.h> +#include <process.h> #include "wine/test.h" #include "winnls.h" @@ -27,6 +28,9 @@ static BOOL (__cdecl *p__crtGetStringTypeW)(DWORD, DWORD, const wchar_t*, int, W static int (__cdecl *pmemcpy_s)(void *, size_t, void*, size_t); static int (__cdecl *p___mb_cur_max_func)(void); static int *(__cdecl *p__p___mb_cur_max)(void); +static _locale_t(__cdecl *p_create_locale)(int, const char*); +static void(__cdecl *p_free_locale)(_locale_t); +static int (__cdecl *p_wcsicmp_l)(const wchar_t*, const wchar_t*, _locale_t); void* __cdecl _Gettnames(void); static void init(void) @@ -37,6 +41,9 @@ static void init(void) pmemcpy_s = (void*)GetProcAddress(hmod, "memcpy_s"); p___mb_cur_max_func = (void*)GetProcAddress(hmod, "___mb_cur_max_func"); p__p___mb_cur_max = (void*)GetProcAddress(hmod, "__p___mb_cur_max"); + p_create_locale = (void*)GetProcAddress(hmod, "_create_locale"); + p_free_locale = (void*)GetProcAddress(hmod, "_free_locale"); + p_wcsicmp_l = (void*)GetProcAddress(hmod, "_wcsicmp_l"); } static void test_setlocale(void) @@ -45,6 +52,8 @@ static void test_setlocale(void) "LC_MONETARY=Greek_Greece.1253;LC_NUMERIC=Polish_Poland.1250;LC_TIME=C"; char *ret, buf[100]; + char *ptr; + int len; ret = setlocale(20, "C"); ok(ret == NULL, "ret = %s\n", ret); @@ -571,12 +580,14 @@ static void test_setlocale(void) ret = setlocale(LC_ALL, "trk"); ok(ret != NULL || broken (ret == NULL), "ret == NULL\n"); if(ret) - ok(!strcmp(ret, "Turkish_Turkey.1254"), "ret = %s\n", ret); + ok(!strcmp(ret, "Turkish_Turkey.1254") + || !strcmp(ret, "Turkish_T\xfcrkiye.1254"), "ret = %s\n", ret); ret = setlocale(LC_ALL, "turkish"); ok(ret != NULL || broken (ret == NULL), "ret == NULL\n"); if(ret) - ok(!strcmp(ret, "Turkish_Turkey.1254"), "ret = %s\n", ret); + ok(!strcmp(ret, "Turkish_Turkey.1254") + || !strcmp(ret, "Turkish_T\xfcrkiye.1254"), "ret = %s\n", ret); ret = setlocale(LC_ALL, "uk"); ok(ret != NULL, "ret == NULL\n"); @@ -612,6 +623,27 @@ static void test_setlocale(void) ok(!strcmp(ret, buf), "ret = %s, expected %s\n", ret, buf); } + GetLocaleInfoA(GetUserDefaultLCID(), LOCALE_IDEFAULTCODEPAGE, buf, sizeof(buf)); + if(IsValidCodePage(atoi(buf))) { + ret = setlocale(LC_ALL, ".OCP"); + ok(ret != NULL, "ret == NULL\n"); + ptr = strchr(ret, '.'); + ok(ptr && !strcmp(ptr + 1, buf), "ret %s, buf %s.\n", ret, buf); + } + + len = GetLocaleInfoA(GetUserDefaultLCID(), LOCALE_IDEFAULTANSICODEPAGE, buf, sizeof(buf)) - 1; + if(buf[0] == '0' && !buf[1]) + len = sprintf(buf, "%d", GetACP()); + ret = setlocale(LC_ALL, ".ACP"); + ok(ret != NULL, "ret == NULL\n"); + ptr = strchr(ret, '.'); + ok(ptr && !strncmp(ptr + 1, buf, len), "ret %s, buf %s.\n", ret, buf); + + ret = setlocale(LC_ALL, ".1250"); + ok(ret != NULL, "ret == NULL\n"); + ptr = strchr(ret, '.'); + ok(ptr && !strcmp(ptr, ".1250"), "ret %s, buf %s.\n", ret, buf); + ret = setlocale(LC_ALL, "English_United States.UTF8"); ok(ret == NULL, "ret != NULL\n"); @@ -621,13 +653,7 @@ static void test_setlocale(void) static void test_crtGetStringTypeW(void) { - static const wchar_t str0[] = { '0', '\0' }; - static const wchar_t strA[] = { 'A', '\0' }; - static const wchar_t str_space[] = { ' ', '\0' }; - static const wchar_t str_null[] = { '\0', '\0' }; - static const wchar_t str_rand[] = { 1234, '\0' }; - - const wchar_t *str[] = { str0, strA, str_space, str_null, str_rand }; + const wchar_t *str[] = { L"0", L"A", L" ", L"\0", L"\x04d2" }; WORD out_crt, out; BOOL ret_crt, ret; @@ -712,10 +738,14 @@ static void test__Gettnames(void) { size = GetLocaleInfoA(MAKELCID(LANG_ENGLISH, SORT_DEFAULT), time_data[i], buf, sizeof(buf)); - ok(size, "GetLocaleInfo failed: %x\n", GetLastError()); + ok(size, "GetLocaleInfo failed: %lx\n", GetLastError()); ok(!strcmp(ret->str[i], buf), "ret->str[%i] = %s, expected %s\n", i, ret->str[i], buf); } + ok(ret->wstr[0] != NULL, "ret->wstr[0] = NULL\n"); + ok(ret->str[42] + strlen(ret->str[42])+1 != (char*)ret->wstr[0], + "ret->str[42] = %p len = %Id, ret->wstr[0] = %p\n", + ret->str[42], strlen(ret->str[42]), ret->wstr[0]); free(ret); if(!setlocale(LC_TIME, "german")) @@ -726,7 +756,7 @@ static void test__Gettnames(void) { size = GetLocaleInfoA(MAKELCID(LANG_GERMAN, SORT_DEFAULT), time_data[i], buf, sizeof(buf)); - ok(size, "GetLocaleInfo failed: %x\n", GetLastError()); + ok(size, "GetLocaleInfo failed: %lx\n", GetLastError()); ok(!strcmp(ret->str[i], buf), "ret->str[%i] = %s, expected %s\n", i, ret->str[i], buf); } free(ret); @@ -775,6 +805,178 @@ static void test___mb_cur_max_func(void) } } +static void test__wcsicmp_l(void) +{ + const struct { + const wchar_t *str1; + const wchar_t *str2; + int exp; + const char *loc; + } tests[] = { + { L"i", L"i", 0 }, + { L"I", L"i", 0 }, + { L"I", L"i", 0, "Turkish" }, + { L"i", L"a", 8 }, + { L"a", L"i", -8 }, + { L"i", L"a", 8, "Turkish" }, + }; + int ret, i; + + if (!p_wcsicmp_l || !p_create_locale) + { + win_skip("_wcsicmp_l or _create_locale not available\n"); + return; + } + ok(!!p_free_locale, "_free_locale not available\n"); + + for(i=0; i<ARRAY_SIZE(tests); i++) { + _locale_t loc = NULL; + + if(tests[i].loc && !(loc = p_create_locale(LC_ALL, tests[i].loc))) { + win_skip("locale %s not available. skipping\n", tests[i].loc); + continue; + } + + ret = p_wcsicmp_l(tests[i].str1, tests[i].str2, loc); + ok(ret == tests[i].exp, "_wcsicmp_l = %d, expected %d for test %d '%ls' vs '%ls' using %s locale\n", + ret, tests[i].exp, i, tests[i].str1, tests[i].str2, loc ? tests[i].loc : "current"); + + if(loc) + p_free_locale(loc); + } +} + +static unsigned __stdcall test_thread_setlocale_func(void *arg) +{ + char *ret; + + ret = setlocale(LC_ALL, NULL); + ok(!strcmp(ret, "C"), "expected ret=C, but received ret=%s\n", ret); + + ret = setlocale(LC_ALL, ""); + ok(strcmp(ret, "Invariant Language_Invariant Country.0"), "expected valid locale\n"); + + return 0; +} + +static void test_thread_setlocale(void) +{ + HANDLE hThread; + + hThread = (HANDLE)_beginthreadex(NULL, 0, test_thread_setlocale_func, NULL, 0, NULL); + ok(hThread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno); + WaitForSingleObject(hThread, 5000); + CloseHandle(hThread); +} + +static void test_locale_info(void) +{ + pthreadlocinfo locinfo, locinfo2; + _locale_t locale, locale2; + int ret; + + if (!p_create_locale) + { + win_skip("_create_locale isn't available.\n"); + return; + } + + if (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_JAPANESE) + skip("Skip language-specific tests on Japanese system.\n"); + else + { + locale = p_create_locale(LC_ALL, "Japanese_Japan.932"); + locale2 = p_create_locale(LC_ALL, ".932"); + locinfo = locale->locinfo; + locinfo2 = locale2->locinfo; + + ok(locinfo->mb_cur_max == locinfo2->mb_cur_max, "Got wrong max char size %d %d.\n", + locinfo->mb_cur_max, locinfo2->mb_cur_max); + ok(locinfo->ctype1_refcount != locinfo2->ctype1_refcount, "Got wrong refcount pointer %p vs %p.\n", + locinfo->ctype1_refcount, locinfo2->ctype1_refcount); + ok(locinfo->lc_codepage == 932 && locinfo->lc_codepage == locinfo2->lc_codepage, + "Got wrong codepage %d vs %d.\n", locinfo->lc_codepage, locinfo2->lc_codepage); + ok(locinfo->lc_id[LC_CTYPE].wCodePage == 932 + && locinfo->lc_id[LC_CTYPE].wCodePage == locinfo2->lc_id[LC_CTYPE].wCodePage, + "Got wrong LC_CTYPE codepage %d vs %d.\n", locinfo->lc_id[LC_CTYPE].wCodePage, + locinfo2->lc_id[LC_CTYPE].wCodePage); + ret = strcmp(locinfo->lc_category[LC_CTYPE].locale, locinfo2->lc_category[LC_CTYPE].locale); + ok(!!ret, "Got locale name %s vs %s.\n", locinfo->lc_category[LC_CTYPE].locale, + locinfo2->lc_category[LC_CTYPE].locale); + ret = memcmp(locinfo->ctype1, locinfo2->ctype1, 257 * sizeof(*locinfo->ctype1)); + ok(!ret, "Got wrong ctype1 data.\n"); + ret = memcmp(locinfo->pclmap, locinfo2->pclmap, 256 * sizeof(*locinfo->pclmap)); + ok(!ret, "Got wrong pclmap data.\n"); + ret = memcmp(locinfo->pcumap, locinfo2->pcumap, 256 * sizeof(*locinfo->pcumap)); + ok(!ret, "Got wrong pcumap data.\n"); + ok(locinfo->lc_handle[LC_CTYPE] != locinfo2->lc_handle[LC_CTYPE], + "Got wrong LC_CTYPE %#lx vs %#lx.\n", locinfo->lc_handle[LC_CTYPE], locinfo2->lc_handle[LC_CTYPE]); + + p_free_locale(locale2); + locale2 = p_create_locale(LC_ALL, "Japanese_Japan.1252"); + locinfo2 = locale2->locinfo; + + ok(locinfo->mb_cur_max != locinfo2->mb_cur_max, "Got wrong max char size %d %d.\n", + locinfo->mb_cur_max, locinfo2->mb_cur_max); + ok(locinfo->ctype1_refcount != locinfo2->ctype1_refcount, "Got wrong refcount pointer %p vs %p.\n", + locinfo->ctype1_refcount, locinfo2->ctype1_refcount); + ok(locinfo2->lc_codepage == 1252, "Got wrong codepage %d.\n", locinfo2->lc_codepage); + ok(locinfo2->lc_id[LC_CTYPE].wCodePage == 1252, "Got wrong LC_CTYPE codepage %d.\n", + locinfo2->lc_id[LC_CTYPE].wCodePage); + ok(locinfo->lc_codepage != locinfo2->lc_codepage, "Got wrong codepage %d vs %d.\n", + locinfo->lc_codepage, locinfo2->lc_codepage); + ok(locinfo->lc_id[LC_CTYPE].wCodePage != locinfo2->lc_id[LC_CTYPE].wCodePage, + "Got wrong LC_CTYPE codepage %d vs %d.\n", locinfo->lc_id[LC_CTYPE].wCodePage, + locinfo2->lc_id[LC_CTYPE].wCodePage); + ret = strcmp(locinfo->lc_category[LC_CTYPE].locale, locinfo2->lc_category[LC_CTYPE].locale); + ok(!!ret, "Got locale name %s vs %s.\n", locinfo->lc_category[LC_CTYPE].locale, + locinfo2->lc_category[LC_CTYPE].locale); + ret = memcmp(locinfo->ctype1, locinfo2->ctype1, 257 * sizeof(*locinfo->ctype1)); + ok(!!ret, "Got wrong ctype1 data.\n"); + ret = memcmp(locinfo->pclmap, locinfo2->pclmap, 256 * sizeof(*locinfo->pclmap)); + ok(!!ret, "Got wrong pclmap data.\n"); + ret = memcmp(locinfo->pcumap, locinfo2->pcumap, 256 * sizeof(*locinfo->pcumap)); + ok(!!ret, "Got wrong pcumap data.\n"); + ok(locinfo->lc_handle[LC_CTYPE] == locinfo2->lc_handle[LC_CTYPE], + "Got wrong LC_CTYPE %#lx vs %#lx.\n", locinfo->lc_handle[LC_CTYPE], locinfo2->lc_handle[LC_CTYPE]); + + p_free_locale(locale2); + locale2 = p_create_locale(LC_ALL, "Japanese_Japan.3000"); /* an invalid codepage */ + ok(!locale2, "Got %p.\n", locale2); + + p_free_locale(locale); + } + + locale = p_create_locale(LC_ALL, "German_Germany.437"); + locale2 = p_create_locale(LC_ALL, "German_Germany.1252"); + locinfo = locale->locinfo; + locinfo2 = locale2->locinfo; + + ok(locinfo->mb_cur_max == locinfo2->mb_cur_max, "Got wrong max char size %d %d.\n", + locinfo->mb_cur_max, locinfo2->mb_cur_max); + ok(locinfo->ctype1_refcount != locinfo2->ctype1_refcount, "Got wrong refcount pointer %p vs %p.\n", + locinfo->ctype1_refcount, locinfo2->ctype1_refcount); + ok(locinfo->lc_codepage != locinfo2->lc_codepage, "Got wrong codepage %d vs %d.\n", + locinfo->lc_codepage, locinfo2->lc_codepage); + ok(locinfo->lc_id[LC_CTYPE].wCodePage != locinfo2->lc_id[LC_CTYPE].wCodePage, + "Got wrong LC_CTYPE codepage %d vs %d.\n", locinfo->lc_id[LC_CTYPE].wCodePage, + locinfo2->lc_id[LC_CTYPE].wCodePage); + ret = strcmp(locinfo->lc_category[LC_CTYPE].locale, locinfo2->lc_category[LC_CTYPE].locale); + ok(!!ret, "Got locale name %s vs %s.\n", locinfo->lc_category[LC_CTYPE].locale, + locinfo2->lc_category[LC_CTYPE].locale); + ret = memcmp(locinfo->ctype1, locinfo2->ctype1, 257 * sizeof(*locinfo->ctype1)); + ok(!!ret, "Got wrong ctype1 data.\n"); + ret = memcmp(locinfo->pclmap, locinfo2->pclmap, 256 * sizeof(*locinfo->pclmap)); + ok(!!ret, "Got wrong pclmap data.\n"); + ret = memcmp(locinfo->pcumap, locinfo2->pcumap, 256 * sizeof(*locinfo->pcumap)); + ok(!!ret, "Got wrong pcumap data.\n"); + ok(locinfo->lc_handle[LC_CTYPE] == locinfo2->lc_handle[LC_CTYPE], + "Got wrong LC_CTYPE %#lx vs %#lx.\n", locinfo->lc_handle[LC_CTYPE], locinfo2->lc_handle[LC_CTYPE]); + + p_free_locale(locale2); + p_free_locale(locale); +} + START_TEST(locale) { init(); @@ -783,4 +985,7 @@ START_TEST(locale) test_setlocale(); test__Gettnames(); test___mb_cur_max_func(); + test__wcsicmp_l(); + test_thread_setlocale(); + test_locale_info(); } diff --git a/modules/rostests/winetests/msvcrt/misc.c b/modules/rostests/winetests/msvcrt/misc.c index d82f71e122e..7b54b3aeb88 100644 --- a/modules/rostests/winetests/msvcrt/misc.c +++ b/modules/rostests/winetests/msvcrt/misc.c @@ -20,31 +20,12 @@ #include "wine/test.h" #include <errno.h> +#include <fcntl.h> +#include <io.h> #include <stdio.h> #include <math.h> -#include "msvcrt.h" #include <process.h> -static inline float __port_infinity(void) -{ - static const unsigned __inf_bytes = 0x7f800000; - return *(const float *)&__inf_bytes; -} -#ifdef __REACTOS__ -#undef INFINITY -#endif -#define INFINITY __port_infinity() - -static inline float __port_nan(void) -{ - static const unsigned __nan_bytes = 0x7fc00000; - return *(const float *)&__nan_bytes; -} -#ifdef __REACTOS__ -#undef NAN -#endif -#define NAN __port_nan() - static inline BOOL almost_equal(double d1, double d2) { if(d1-d2>-1e-30 && d1-d2<1e-30) return TRUE; @@ -56,14 +37,14 @@ struct uld { ULONG lo, hi, exp; }; static int (__cdecl *prand_s)(unsigned int *); static int (__cdecl *pI10_OUTPUT)(struct uld, int, int, void*); -static int (__cdecl *pstrerror_s)(char *, MSVCRT_size_t, int); +static int (__cdecl *pstrerror_s)(char *, size_t, int); static int (__cdecl *p_get_doserrno)(int *); static int (__cdecl *p_get_errno)(int *); static int (__cdecl *p_set_doserrno)(int); static int (__cdecl *p_set_errno)(int); static void (__cdecl *p__invalid_parameter)(const wchar_t*, const wchar_t*, const wchar_t*, unsigned int, uintptr_t); -static void (__cdecl *p_qsort_s)(void*, MSVCRT_size_t, MSVCRT_size_t, +static void (__cdecl *p_qsort_s)(void*, size_t, size_t, int (__cdecl*)(void*, const void*, const void*), void*); static double (__cdecl *p_atan)(double); static double (__cdecl *p_exp)(double); @@ -194,7 +175,7 @@ static void test_I10_OUTPUT(void) j = strlen(I10_OUTPUT_tests[i].remain); todo_wine_if(j && I10_OUTPUT_tests[i].remain[j-1]=='9') ok(!strncmp(out.str+out.len+1, I10_OUTPUT_tests[i].remain, j), - "%d: &out.str[%d] = %.25s...\n", i, out.len+1, out.str+out.len+1); + "%d: &out.str[%d] = %.25s...\n", i, out.len+1, out.str+out.len+1); for(j=out.len+strlen(I10_OUTPUT_tests[i].remain)+1; j<sizeof(out.str); j++) if(out.str[j] != '#') @@ -233,7 +214,7 @@ static void test_strerror_s(void) memset(buf, 'X', sizeof(buf)); ret = pstrerror_s(buf, 1, 0); ok(ret == 0, "Expected strerror_s to return 0, got %d\n", ret); - ok(strlen(buf) == 0, "Expected output buffer to be null terminated\n"); + ok(buf[0] == 0, "Expected output buffer to be null terminated\n"); memset(buf, 'X', sizeof(buf)); ret = pstrerror_s(buf, 2, 0); @@ -263,7 +244,7 @@ static void test__get_doserrno(void) errno = EBADF; ret = p_get_doserrno(NULL); ok(ret == EINVAL, "Expected _get_doserrno to return EINVAL, got %d\n", ret); - ok(_doserrno == ERROR_INVALID_CMM, "Expected _doserrno to be ERROR_INVALID_CMM, got %d\n", _doserrno); + ok(_doserrno == ERROR_INVALID_CMM, "Expected _doserrno to be ERROR_INVALID_CMM, got %ld\n", _doserrno); ok(errno == EBADF, "Expected errno to be EBADF, got %d\n", errno); _doserrno = ERROR_INVALID_CMM; @@ -310,19 +291,19 @@ static void test__set_doserrno(void) ret = p_set_doserrno(ERROR_FILE_NOT_FOUND); ok(ret == 0, "Expected _set_doserrno to return 0, got %d\n", ret); ok(_doserrno == ERROR_FILE_NOT_FOUND, - "Expected _doserrno to be ERROR_FILE_NOT_FOUND, got %d\n", _doserrno); + "Expected _doserrno to be ERROR_FILE_NOT_FOUND, got %ld\n", _doserrno); _doserrno = ERROR_INVALID_CMM; ret = p_set_doserrno(-1); ok(ret == 0, "Expected _set_doserrno to return 0, got %d\n", ret); ok(_doserrno == -1, - "Expected _doserrno to be -1, got %d\n", _doserrno); + "Expected _doserrno to be -1, got %ld\n", _doserrno); _doserrno = ERROR_INVALID_CMM; ret = p_set_doserrno(0xdeadbeef); ok(ret == 0, "Expected _set_doserrno to return 0, got %d\n", ret); ok(_doserrno == 0xdeadbeef, - "Expected _doserrno to be 0xdeadbeef, got %d\n", _doserrno); + "Expected _doserrno to be 0xdeadbeef, got %ld\n", _doserrno); } static void test__set_errno(void) @@ -351,21 +332,42 @@ static void test__set_errno(void) ok(errno == 0xdeadbeef, "Expected errno to be 0xdeadbeef, got %d\n", errno); } -static void test__popen_child(void) +static void test__popen_child(int fd) { /* don't execute any tests here */ /* ExitProcess is used to set return code of _pclose */ printf("child output\n"); + if ((HANDLE)_get_osfhandle(fd) != INVALID_HANDLE_VALUE) + ExitProcess(1); ExitProcess(0x37); } +static void test__popen_read_child(void) +{ + char buf[1024], *rets; + + rets = fgets(buf, sizeof(buf), stdin); + if (strcmp(buf, "child-to-parent\n") != 0) + ExitProcess(1); + + rets = fgets(buf, sizeof(buf), stdin); + if (rets) + ExitProcess(2); + ExitProcess(3); +} + static void test__popen(const char *name) { FILE *pipe; - char buf[1024]; - int ret; + char *tempf, buf[1024]; + int ret, fd; + + tempf = _tempnam(".", "wne"); + ok(tempf != NULL, "_tempnam failed\n"); + fd = _open(tempf, _O_CREAT | _O_WRONLY); + ok(fd != -1, "open failed\n"); - sprintf(buf, "\"%s\" misc popen", name); + sprintf(buf, "\"%s\" misc popen %d", name, fd); pipe = _popen(buf, "r"); ok(pipe != NULL, "_popen failed with error: %d\n", errno); @@ -374,12 +376,25 @@ static void test__popen(const char *name) ret = _pclose(pipe); ok(ret == 0x37, "_pclose returned %x, expected 0x37\n", ret); + _close(fd); + _unlink(tempf); + free(tempf); errno = 0xdeadbeef; ret = _pclose((FILE*)0xdeadbeef); ok(ret == -1, "_pclose returned %x, expected -1\n", ret); if(p_set_errno) ok(errno == EBADF, "errno = %d\n", errno); + + sprintf(buf, "\"%s\" misc popen_read", name); + pipe = _popen(buf, "w"); + ok(pipe != NULL, "_popen failed with error: %d\n", errno); + + ret = fputs("child-to-parent\n", pipe); + ok(ret != EOF, "fputs returned %x\n", ret); + + ret = _pclose(pipe); + ok(ret == 0x3, "_pclose returned %x, expected 0x3\n", ret); } static void test__invalid_parameter(void) @@ -512,8 +527,35 @@ static void test_qsort_s(void) ok(tab[i] == i, "data sorted incorrectly on position %d: %d\n", i, tab[i]); } +static int eq_nan(UINT64 ai, double b) +{ + UINT64 bi = *(UINT64*)&b; + UINT64 mask; + +#if defined(__i386__) + mask = 0xFFFFFFFF00000000ULL; +#else + mask = ~0; +#endif + + ok((ai & mask) == (bi & mask), "comparing %s and %s\n", + wine_dbgstr_longlong(ai), wine_dbgstr_longlong(bi)); + return (ai & mask) == (bi & mask); +} + +static int eq_nanf(DWORD ai, float b) +{ + DWORD bi = *(DWORD*)&b; + ok(ai == bi, "comparing %08lx and %08lx\n", ai, bi); + return ai == bi; +} + static void test_math_functions(void) { + static const UINT64 test_nan_i = 0xFFF0000123456780ULL; + static const DWORD test_nanf_i = 0xFF801234; + double test_nan = *(double*)&test_nan_i; + float test_nanf = *(float*)&test_nanf_i; double ret; errno = 0xdeadbeef; @@ -546,6 +588,13 @@ static void test_math_functions(void) errno = 0xdeadbeef; p_exp(INFINITY); ok(errno == 0xdeadbeef, "errno = %d\n", errno); + + ok(eq_nan(test_nan_i | (1ULL << 51), cosh(test_nan)), "cosh not preserving nan\n"); + ok(eq_nan(test_nan_i | (1ULL << 51), sinh(test_nan)), "sinh not preserving nan\n"); + ok(eq_nan(test_nan_i | (1ULL << 51), tanh(test_nan)), "tanh not preserving nan\n"); + ok(eq_nanf(test_nanf_i | (1 << 22), coshf(test_nanf)), "coshf not preserving nan\n"); + ok(eq_nanf(test_nanf_i | (1 << 22), sinhf(test_nanf)), "sinhf not preserving nan\n"); + ok(eq_nanf(test_nanf_i | (1 << 22), tanhf(test_nanf)), "tanhf not preserving nan\n"); } static void __cdecl test_thread_func(void *end_thread_type) @@ -574,38 +623,51 @@ static void test_thread_handle_close(void) ok(hThread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno); WaitForSingleObject(hThread, INFINITE); ret = CloseHandle(hThread); - ok(!ret, "ret = %d\n", ret); + ok(!ret, "ret = %ld\n", ret); hThread = (HANDLE)_beginthread(test_thread_func, 0, (void*)1); ok(hThread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno); WaitForSingleObject(hThread, INFINITE); ret = CloseHandle(hThread); - ok(!ret, "ret = %d\n", ret); + ok(!ret, "ret = %ld\n", ret); hThread = (HANDLE)_beginthread(test_thread_func, 0, (void*)2); ok(hThread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno); Sleep(150); ret = WaitForSingleObject(hThread, INFINITE); - ok(ret == WAIT_OBJECT_0, "ret = %d\n", ret); + ok(ret == WAIT_OBJECT_0, "ret = %ld\n", ret); ret = CloseHandle(hThread); - ok(ret, "ret = %d\n", ret); + ok(ret, "ret = %ld\n", ret); hThread = (HANDLE)_beginthread(test_thread_func, 0, (void*)3); ok(hThread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno); Sleep(150); ret = WaitForSingleObject(hThread, INFINITE); - ok(ret == WAIT_OBJECT_0, "ret = %d\n", ret); + ok(ret == WAIT_OBJECT_0, "ret = %ld\n", ret); ret = CloseHandle(hThread); - ok(ret, "ret = %d\n", ret); + ok(ret, "ret = %ld\n", ret); /* _beginthreadex: handle is not closed on _endthread */ hThread = (HANDLE)_beginthreadex(NULL,0, test_thread_func_ex, NULL, 0, NULL); ok(hThread != NULL, "_beginthreadex failed (%d)\n", errno); Sleep(150); ret = WaitForSingleObject(hThread, INFINITE); - ok(ret == WAIT_OBJECT_0, "ret = %d\n", ret); + ok(ret == WAIT_OBJECT_0, "ret = %ld\n", ret); ret = CloseHandle(hThread); - ok(ret, "ret = %d\n", ret); + ok(ret, "ret = %ld\n", ret); +} + +static void test_thread_suspended(void) +{ + HANDLE hThread; + DWORD ret; + + hThread = (HANDLE)_beginthreadex(NULL, 0, test_thread_func_ex, NULL, CREATE_SUSPENDED, NULL); + ok(hThread != NULL, "_beginthreadex failed (%d)\n", errno); + ret = ResumeThread(hThread); + ok(ret == 1, "suspend count = %ld\n", ret); + ret = WaitForSingleObject(hThread, 200); + ok(ret == WAIT_OBJECT_0, "ret = %ld\n", ret); } static int __cdecl _lfind_s_comp(void *ctx, const void *l, const void *r) @@ -685,8 +747,10 @@ START_TEST(misc) arg_c = winetest_get_mainargs(&arg_v); if(arg_c >= 3) { - if(!strcmp(arg_v[2], "popen")) - test__popen_child(); + if (!strcmp(arg_v[2], "popen_read")) + test__popen_read_child(); + else if(arg_c == 4 && !strcmp(arg_v[2], "popen")) + test__popen_child(atoi(arg_v[3])); else ok(0, "invalid argument '%s'\n", arg_v[2]); @@ -705,5 +769,6 @@ START_TEST(misc) test_qsort_s(); test_math_functions(); test_thread_handle_close(); + test_thread_suspended(); test__lfind_s(); } diff --git a/modules/rostests/winetests/msvcrt/printf.c b/modules/rostests/winetests/msvcrt/printf.c index 4bf55afc1ff..dc0038b3372 100644 --- a/modules/rostests/winetests/msvcrt/printf.c +++ b/modules/rostests/winetests/msvcrt/printf.c @@ -23,9 +23,7 @@ /* With Visual Studio >= 2005, swprintf() takes an extra parameter unless * the following macro is defined. */ -#ifndef _CRT_NON_CONFORMING_SWPRINTFS #define _CRT_NON_CONFORMING_SWPRINTFS -#endif #include <stdio.h> #include <errno.h> @@ -38,24 +36,6 @@ #include "wine/test.h" -#ifndef __REACTOS__ - -static inline float __port_infinity(void) -{ - static const unsigned __inf_bytes = 0x7f800000; - return *(const float *)&__inf_bytes; -} -#define INFINITY __port_infinity() - -static inline float __port_nan(void) -{ - static const unsigned __nan_bytes = 0x7fc00000; - return *(const float *)&__nan_bytes; -} -#define NAN __port_nan() - -#endif - static inline float __port_ind(void) { static const unsigned __ind_bytes = 0xffc00000; @@ -63,11 +43,11 @@ static inline float __port_ind(void) } #define IND __port_ind() -static int (__cdecl *p__vscprintf)(const char *format, __ms_va_list valist); -static int (__cdecl *p__vscwprintf)(const wchar_t *format, __ms_va_list valist); +static int (__cdecl *p__vscprintf)(const char *format, va_list valist); +static int (__cdecl *p__vscwprintf)(const wchar_t *format, va_list valist); static int (__cdecl *p__vsnwprintf_s)(wchar_t *str, size_t sizeOfBuffer, size_t count, const wchar_t *format, - __ms_va_list valist); + va_list valist); static int (__cdecl *p__ecvt_s)(char *buffer, size_t length, double number, int ndigits, int *decpt, int *sign); static int (__cdecl *p__fcvt_s)(char *buffer, size_t length, double number, @@ -75,17 +55,17 @@ static int (__cdecl *p__fcvt_s)(char *buffer, size_t length, double number, static unsigned int (__cdecl *p__get_output_format)(void); static unsigned int (__cdecl *p__set_output_format)(unsigned int); static int (WINAPIV *p_sprintf)(char*, ...); -static int (__cdecl *p__vsprintf_p)(char*, size_t, const char*, __ms_va_list); -static int (__cdecl *p_vswprintf)(wchar_t *str, const wchar_t *format, __ms_va_list valist); -static int (__cdecl *p__vswprintf)(wchar_t *str, const wchar_t *format, __ms_va_list valist); +static int (__cdecl *p__vsprintf_p)(char*, size_t, const char*, va_list); +static int (__cdecl *p_vswprintf)(wchar_t *str, const wchar_t *format, va_list valist); +static int (__cdecl *p__vswprintf)(wchar_t *str, const wchar_t *format, va_list valist); static int (__cdecl *p__vswprintf_l)(wchar_t *str, const wchar_t *format, - void *locale, __ms_va_list valist); + void *locale, va_list valist); static int (__cdecl *p__vswprintf_c)(wchar_t *str, size_t size, const wchar_t *format, - __ms_va_list valist); + va_list valist); static int (__cdecl *p__vswprintf_c_l)(wchar_t *str, size_t size, const wchar_t *format, - void *locale, __ms_va_list valist); + void *locale, va_list valist); static int (__cdecl *p__vswprintf_p_l)(wchar_t *str, size_t size, const wchar_t *format, - void *locale, __ms_va_list valist); + void *locale, va_list valist); static void init( void ) { @@ -110,466 +90,295 @@ static void init( void ) static void test_sprintf( void ) { - char buffer[100]; - const char *format; - double pnumber=789456123; - int x, r; - WCHAR wide[] = { 'w','i','d','e',0}; - WCHAR buf_w[2]; - - format = "%+#23.15e"; - r = p_sprintf(buffer,format,pnumber); - ok(!strcmp(buffer,"+7.894561230000000e+008"),"+#23.15e failed: '%s'\n", buffer); - ok( r==23, "return count wrong\n"); - - format = "%-#23.15e"; - r = p_sprintf(buffer,format,pnumber); - ok(!strcmp(buffer,"7.894561230000000e+008 "),"-#23.15e failed: '%s'\n", buffer); - ok( r==23, "return count wrong\n"); - - format = "%#23.15e"; - r = p_sprintf(buffer,format,pnumber); - ok(!strcmp(buffer," 7.894561230000000e+008"),"#23.15e failed: '%s'\n", buffer); - ok( r==23, "return count wrong\n"); - - format = "%#1.1g"; - r = p_sprintf(buffer,format,pnumber); - ok(!strcmp(buffer,"8.e+008"),"#1.1g failed: '%s'\n", buffer); - ok( r==7, "return count wrong\n"); - - format = "%I64d"; - r = p_sprintf(buffer,format,((ULONGLONG)0xffffffff)*0xffffffff); - ok(!strcmp(buffer,"-8589934591"),"Problem with long long\n"); - ok( r==11, "return count wrong\n"); - - format = "%+8I64d"; - r = p_sprintf(buffer,format,(LONGLONG)100); - ok(!strcmp(buffer," +100") && r==8,"+8I64d failed: '%s'\n", buffer); - - format = "%+.8I64d"; - r = p_sprintf(buffer,format,(LONGLONG)100); - ok(!strcmp(buffer,"+00000100") && r==9,"+.8I64d failed: '%s'\n", buffer); - - format = "%+10.8I64d"; - r = p_sprintf(buffer,format,(LONGLONG)100); - ok(!strcmp(buffer," +00000100") && r==10,"+10.8I64d failed: '%s'\n", buffer); - format = "%_1I64d"; - r = p_sprintf(buffer,format,(LONGLONG)100); - ok(!strcmp(buffer,"_1I64d") && r==6,"_1I64d failed\n"); - - format = "%-1.5I64d"; - r = p_sprintf(buffer,format,(LONGLONG)-100); - ok(!strcmp(buffer,"-00100") && r==6,"-1.5I64d failed: '%s'\n", buffer); - - format = "%5I64d"; - r = p_sprintf(buffer,format,(LONGLONG)100); - ok(!strcmp(buffer," 100") && r==5,"5I64d failed: '%s'\n", buffer); - - format = "%5I64d"; - r = p_sprintf(buffer,format,(LONGLONG)-100); - ok(!strcmp(buffer," -100") && r==5,"5I64d failed: '%s'\n", buffer); - - format = "%-5I64d"; - r = p_sprintf(buffer,format,(LONGLONG)100); - ok(!strcmp(buffer,"100 ") && r==5,"-5I64d failed: '%s'\n", buffer); - - format = "%-5I64d"; - r = p_sprintf(buffer,format,(LONGLONG)-100); - ok(!strcmp(buffer,"-100 ") && r==5,"-5I64d failed: '%s'\n", buffer); - - format = "%-.5I64d"; - r = p_sprintf(buffer,format,(LONGLONG)100); - ok(!strcmp(buffer,"00100") && r==5,"-.5I64d failed: '%s'\n", buffer); - - format = "%-.5I64d"; - r = p_sprintf(buffer,format,(LONGLONG)-100); - ok(!strcmp(buffer,"-00100") && r==6,"-.5I64d failed: '%s'\n", buffer); - - format = "%-8.5I64d"; - r = p_sprintf(buffer,format,(LONGLONG)100); - ok(!strcmp(buffer,"00100 ") && r==8,"-8.5I64d failed: '%s'\n", buffer); - - format = "%-8.5I64d"; - r = p_sprintf(buffer,format,(LONGLONG)-100); - ok(!strcmp(buffer,"-00100 ") && r==8,"-8.5I64d failed: '%s'\n", buffer); - - format = "%05I64d"; - r = p_sprintf(buffer,format,(LONGLONG)100); - ok(!strcmp(buffer,"00100") && r==5,"05I64d failed: '%s'\n", buffer); - - format = "%05I64d"; - r = p_sprintf(buffer,format,(LONGLONG)-100); - ok(!strcmp(buffer,"-0100") && r==5,"05I64d failed: '%s'\n", buffer); - - format = "% I64d"; - r = p_sprintf(buffer,format,(LONGLONG)100); - ok(!strcmp(buffer," 100") && r==4,"' I64d' failed: '%s'\n", buffer); - - format = "% I64d"; - r = p_sprintf(buffer,format,(LONGLONG)-100); - ok(!strcmp(buffer,"-100") && r==4,"' I64d' failed: '%s'\n", buffer); - - format = "% 5I64d"; - r = p_sprintf(buffer,format,(LONGLONG)100); - ok(!strcmp(buffer," 100") && r==5,"' 5I64d' failed: '%s'\n", buffer); - - format = "% 5I64d"; - r = p_sprintf(buffer,format,(LONGLONG)-100); - ok(!strcmp(buffer," -100") && r==5,"' 5I64d' failed: '%s'\n", buffer); - - format = "% .5I64d"; - r = p_sprintf(buffer,format,(LONGLONG)100); - ok(!strcmp(buffer," 00100") && r==6,"' .5I64d' failed: '%s'\n", buffer); - - format = "% .5I64d"; - r = p_sprintf(buffer,format,(LONGLONG)-100); - ok(!strcmp(buffer,"-00100") && r==6,"' .5I64d' failed: '%s'\n", buffer); - - format = "% 8.5I64d"; - r = p_sprintf(buffer,format,(LONGLONG)100); - ok(!strcmp(buffer," 00100") && r==8,"' 8.5I64d' failed: '%s'\n", buffer); - - format = "% 8.5I64d"; - r = p_sprintf(buffer,format,(LONGLONG)-100); - ok(!strcmp(buffer," -00100") && r==8,"' 8.5I64d' failed: '%s'\n", buffer); - - format = "%.0I64d"; - r = p_sprintf(buffer,format,(LONGLONG)0); - ok(r==0,".0I64d failed: '%s'\n", buffer); - - format = "%#+21.18I64x"; - r = p_sprintf(buffer,format,(LONGLONG)-100); - ok(!strcmp(buffer," 0x00ffffffffffffff9c") && r==21,"#+21.18I64x failed: '%s'\n", buffer); - - format = "%#.25I64o"; - r = p_sprintf(buffer,format,(LONGLONG)-100); - ok(!strcmp(buffer,"0001777777777777777777634") && r==25,"#.25I64o failed: '%s'\n", buffer); - - format = "%#+24.20I64o"; - r = p_sprintf(buffer,format,(LONGLONG)-100); - ok(!strcmp(buffer," 01777777777777777777634") && r==24,"#+24.20I64o failed: '%s'\n", buffer); - - format = "%#+18.21I64X"; - r = p_sprintf(buffer,format,(LONGLONG)-100); - ok(!strcmp(buffer,"0X00000FFFFFFFFFFFFFF9C") && r==23,"#+18.21I64X failed: '%s '\n", buffer); - - format = "%#+20.24I64o"; - r = p_sprintf(buffer,format,(LONGLONG)-100); - ok(!strcmp(buffer,"001777777777777777777634") && r==24,"#+20.24I64o failed: '%s'\n", buffer); - - format = "%#+25.22I64u"; - r = p_sprintf(buffer,format,(LONGLONG)-1); - ok(!strcmp(buffer," 0018446744073709551615") && r==25,"#+25.22I64u conversion failed: '%s'\n", buffer); - - format = "%#+25.22I64u"; - r = p_sprintf(buffer,format,(LONGLONG)-1); - ok(!strcmp(buffer," 0018446744073709551615") && r==25,"#+25.22I64u failed: '%s'\n", buffer); - - format = "%#+30.25I64u"; - r = p_sprintf(buffer,format,(LONGLONG)-1); - ok(!strcmp(buffer," 0000018446744073709551615") && r==30,"#+30.25I64u failed: '%s'\n", buffer); - - format = "%+#25.22I64d"; - r = p_sprintf(buffer,format,(LONGLONG)-1); - ok(!strcmp(buffer," -0000000000000000000001") && r==25,"+#25.22I64d failed: '%s'\n", buffer); - - format = "%#-8.5I64o"; - r = p_sprintf(buffer,format,(LONGLONG)100); - ok(!strcmp(buffer,"00144 ") && r==8,"-8.5I64o failed: '%s'\n", buffer); - - format = "%#-+ 08.5I64d"; - r = p_sprintf(buffer,format,(LONGLONG)100); - ok(!strcmp(buffer,"+00100 ") && r==8,"'#-+ 08.5I64d failed: '%s'\n", buffer); - - format = "%#-+ 08.5I64d"; - r = p_sprintf(buffer,format,(LONGLONG)100); - ok(!strcmp(buffer,"+00100 ") && r==8,"#-+ 08.5I64d failed: '%s'\n", buffer); - - format = "%.80I64d"; - r = p_sprintf(buffer,format,(LONGLONG)1); - ok(r==80,"%s format failed\n", format); - - format = "% .80I64d"; - r = p_sprintf(buffer,format,(LONGLONG)1); - ok(r==81,"%s format failed\n", format); - - format = "% .80d"; - r = p_sprintf(buffer,format,1); - ok(r==81,"%s format failed\n", format); - - format = "%lld"; - r = p_sprintf(buffer,format,((ULONGLONG)0xffffffff)*0xffffffff); - ok( r == 1 || r == 11, "return count wrong %d\n", r); - if (r == 11) /* %ll works on Vista */ - ok(!strcmp(buffer, "-8589934591"), "Problem with \"ll\" interpretation '%s'\n", buffer); - else - ok(!strcmp(buffer, "1"), "Problem with \"ll\" interpretation '%s'\n", buffer); + enum { + NO_ARG, + INT_ARG, + ULONGLONG_ARG, + DOUBLE_ARG, + PTR_ARG, + TODO_FLAG = 0x1000 + }; - format = "%I"; - r = p_sprintf(buffer,format,1); - ok(!strcmp(buffer, "I"), "Problem with \"I\" interpretation\n"); - ok( r==1, "return count wrong\n"); + struct { + const char *format; + const char *out; + const char *broken; + int type; + int arg_i; + ULONGLONG arg_ull; + double arg_d; + const void *arg_ptr; + } tests[] = { + { "%+#23.15e", "+7.894561230000000e+008", 0, DOUBLE_ARG, 0, 0, 789456123 }, + { "%-#23.15e", "7.894561230000000e+008 ", 0, DOUBLE_ARG, 0, 0, 789456123 }, + { "%#23.15e", " 7.894561230000000e+008", 0, DOUBLE_ARG, 0, 0, 789456123 }, + { "%#1.1g", "8.e+008", 0, DOUBLE_ARG, 0, 0, 789456123 }, + { "%I64d", "-8589934591", 0, ULONGLONG_ARG, 0, ((ULONGLONG)0xffffffff)*0xffffffff }, + { "%+8I64d", " +100", 0, ULONGLONG_ARG, 0, 100 }, + { "%+.8I64d", "+00000100", 0, ULONGLONG_ARG, 0, 100 }, + { "%+10.8I64d", " +00000100", 0, ULONGLONG_ARG, 0, 100 }, + { "%_1I64d", "_1I64d", 0, ULONGLONG_ARG, 0, 100 }, + { "%-1.5I64d", "-00100", 0, ULONGLONG_ARG, 0, -100 }, + { "%5I64d", " 100", 0, ULONGLONG_ARG, 0, 100 }, + { "%5I64d", " -100", 0, ULONGLONG_ARG, 0, -100 }, + { "%-5I64d", "100 ", 0, ULONGLONG_ARG, 0, 100 }, + { "%-5I64d", "-100 ", 0, ULONGLONG_ARG, 0, -100 }, + { "%-.5I64d", "00100", 0, ULONGLONG_ARG, 0, 100 }, + { "%-.5I64d", "-00100", 0, ULONGLONG_ARG, 0, -100 }, + { "%-8.5I64d", "00100 ", 0, ULONGLONG_ARG, 0, 100 }, + { "%-8.5I64d", "-00100 ", 0, ULONGLONG_ARG, 0, -100 }, + { "%05I64d", "00100", 0, ULONGLONG_ARG, 0, 100 }, + { "%05I64d", "-0100", 0, ULONGLONG_ARG, 0, -100 }, + { "% I64d", " 100", 0, ULONGLONG_ARG, 0, 100 }, + { "% I64d", "-100", 0, ULONGLONG_ARG, 0, -100 }, + { "% 5I64d", " 100", 0, ULONGLONG_ARG, 0, 100 }, + { "% 5I64d", " -100", 0, ULONGLONG_ARG, 0, -100 }, + { "% .5I64d", " 00100", 0, ULONGLONG_ARG, 0, 100 }, + { "% .5I64d", "-00100", 0, ULONGLONG_ARG, 0, -100 }, + { "% 8.5I64d", " 00100", 0, ULONGLONG_ARG, 0, 100 }, + { "% 8.5I64d", " -00100", 0, ULONGLONG_ARG, 0, -100 }, + { "%.0I64d", "", 0, ULONGLONG_ARG }, + { "%#+21.18I64x", " 0x00ffffffffffffff9c", 0, ULONGLONG_ARG, 0, -100 }, + { "%#.25I64o", "0001777777777777777777634", 0, ULONGLONG_ARG, 0, -100 }, + { "%#+24.20I64o", " 01777777777777777777634", 0, ULONGLONG_ARG, 0, -100 }, + { "%#+18.21I64X", "0X00000FFFFFFFFFFFFFF9C", 0, ULONGLONG_ARG, 0, -100 }, + { "%#+20.24I64o", "001777777777777777777634", 0, ULONGLONG_ARG, 0, -100 }, + { "%#+25.22I64u", " 0018446744073709551615", 0, ULONGLONG_ARG, 0, -1 }, + { "%#+25.22I64u", " 0018446744073709551615", 0, ULONGLONG_ARG, 0, -1 }, + { "%#+30.25I64u", " 0000018446744073709551615", 0, ULONGLONG_ARG, 0, -1 }, + { "%+#25.22I64d", " -0000000000000000000001", 0, ULONGLONG_ARG, 0, -1 }, + { "%#-8.5I64o", "00144 ", 0, ULONGLONG_ARG, 0, 100 }, + { "%#-+ 08.5I64d", "+00100 ", 0, ULONGLONG_ARG, 0, 100 }, + { "%.80I64d", + "00000000000000000000000000000000000000000000000000000000000000000000000000000001", + 0, ULONGLONG_ARG, 0, 1 }, + { "% .80I64d", + " 00000000000000000000000000000000000000000000000000000000000000000000000000000001", + 0, ULONGLONG_ARG, 0, 1 }, + { "% .80d", + " 00000000000000000000000000000000000000000000000000000000000000000000000000000001", + 0, INT_ARG, 1 }, + { "%I", "I", 0, INT_ARG, 1 }, + { "%Iq", "Iq", 0, INT_ARG, 1 }, + { "%Ihd", "Ihd", 0, INT_ARG, 1 }, + { "%I0d", "I0d", 0, INT_ARG, 1 }, + { "%I64D", "D", 0, ULONGLONG_ARG, 0, -1 }, + { "%zx", "1", "zx", INT_ARG, 1 }, + { "%z", "z", 0, INT_ARG, 1 }, + { "%tx", "1", "tx", INT_ARG, 1 }, + { "%t", "t", 0, INT_ARG, 1 }, + { "% d", " 1", 0, INT_ARG, 1 }, + { "%+ d", "+1", 0, INT_ARG, 1 }, + { "%S", "wide", 0, PTR_ARG, 0, 0, 0, L"wide" }, + { "%04c", "0001", 0, INT_ARG, '1' }, + { "%-04c", "1 ", 0, INT_ARG, '1' }, + { "%#012x", "0x0000000001", 0, INT_ARG, 1 }, + { "%#012x", "000000000000", 0, INT_ARG, 0 }, + { "%#04.8x", "0x00000001", 0, INT_ARG, 1 }, + { "%#04.8x", "00000000", 0, INT_ARG, 0 }, + { "%#-08.2x", "0x01 ", 0, INT_ARG, 1 }, + { "%#-08.2x", "00 ", 0, INT_ARG, 0 }, + { "%#.0x", "0x1", 0, INT_ARG, 1 }, + { "%#.0x", "", 0, INT_ARG, 0 }, + { "%#08o", "00000001", 0, INT_ARG, 1 }, + { "%#o", "01", 0, INT_ARG, 1 }, + { "%#o", "0", 0, INT_ARG, 0 }, + { "%04s", "0foo", 0, PTR_ARG, 0, 0, 0, "foo" }, + { "%.1s", "f", 0, PTR_ARG, 0, 0, 0, "foo" }, + { "hello", "hello", 0, NO_ARG }, + { "%ws", "wide", 0, PTR_ARG, 0, 0, 0, L"wide" }, + { "%-10ws", "wide ", 0, PTR_ARG, 0, 0, 0, L"wide" }, + { "%10ws", " wide", 0, PTR_ARG, 0, 0, 0, L"wide" }, + { "%#+ -03whlls", "wide", 0, PTR_ARG, 0, 0, 0, L"wide" }, + { "%w0s", "0s", 0, PTR_ARG, 0, 0, 0, L"wide" }, + { "%w-s", "-s", 0, PTR_ARG, 0, 0, 0, L"wide" }, + { "%ls", "wide", 0, PTR_ARG, 0, 0, 0, L"wide" }, + { "%Ls", "not wide", 0, PTR_ARG, 0, 0, 0, "not wide" }, + { "%b", "b", 0, NO_ARG }, + { "%3c", " a", 0, INT_ARG, 'a' }, + { "%3d", "1234", 0, INT_ARG, 1234 }, + { "%3h", "", 0, NO_ARG }, + { "%k%m%q%r%t%v%y%z", "kmqrtvyz", 0, NO_ARG }, + { "%-1d", "2", 0, INT_ARG, 2 }, + { "%2.4f", "8.6000", 0, DOUBLE_ARG, 0, 0, 8.6 }, + { "%0f", "0.600000", 0, DOUBLE_ARG, 0, 0, 0.6 }, + { "%.0f", "1", 0, DOUBLE_ARG, 0, 0, 0.6 }, + { "%2.4e", "8.6000e+000", 0, DOUBLE_ARG, 0, 0, 8.6 }, + { "% 2.4e", " 8.6000e+000", 0, DOUBLE_ARG, 0, 0, 8.6 }, + { "% 014.4e", " 008.6000e+000", 0, DOUBLE_ARG, 0, 0, 8.6 }, + { "% 2.4e", "-8.6000e+000", 0, DOUBLE_ARG, 0, 0, -8.6 }, + { "%+2.4e", "+8.6000e+000", 0, DOUBLE_ARG, 0, 0, 8.6 }, + { "%2.4g", "8.6", 0, DOUBLE_ARG, 0, 0, 8.6 }, + { "%-i", "-1", 0, INT_ARG, -1 }, + { "%-i", "1", 0, INT_ARG, 1 }, + { "%+i", "+1", 0, INT_ARG, 1 }, + { "%o", "12", 0, INT_ARG, 10 }, + { "%s", "(null)", 0, PTR_ARG, 0, 0, 0, NULL }, + { "%s", "%%%%", 0, PTR_ARG, 0, 0, 0, "%%%%" }, + { "%u", "4294967295", 0, INT_ARG, -1 }, + { "%w", "", 0, INT_ARG, -1 }, + { "%h", "", 0, INT_ARG, -1 }, + { "%j", "", "j", ULONGLONG_ARG, 0, -1 }, + { "%jd", "-1", "jd", ULONGLONG_ARG, 0, -1 }, + { "%F", "", 0, INT_ARG, -1 }, + { "%N", "", 0, INT_ARG, -1 }, + { "%H", "H", 0, INT_ARG, -1 }, + { "x%cx", "xXx", 0, INT_ARG, 0x100+'X' }, + { "%%0", "%0", 0, NO_ARG }, + { "%hx", "2345", 0, INT_ARG, 0x12345 }, + { "%hhx", "123", 0, INT_ARG, 0x123 }, + { "%hhx", "2345", 0, INT_ARG, 0x12345 }, + { "%lf", "-1.#IND00", 0, DOUBLE_ARG, 0, 0, IND }, + { "%lf", "1.#QNAN0", 0, DOUBLE_ARG, 0, 0, NAN }, + { "%lf", "1.#INF00", 0, DOUBLE_ARG, 0, 0, INFINITY }, + { "%le", "-1.#IND00e+000", 0, DOUBLE_ARG, 0, 0, IND }, + { "%le", "1.#QNAN0e+000", 0, DOUBLE_ARG, 0, 0, NAN }, + { "%le", "1.#INF00e+000", 0, DOUBLE_ARG, 0, 0, INFINITY }, + { "%lg", "-1.#IND", 0, DOUBLE_ARG, 0, 0, IND }, + { "%lg", "1.#QNAN", 0, DOUBLE_ARG, 0, 0, NAN }, + { "%lg", "1.#INF", 0, DOUBLE_ARG, 0, 0, INFINITY }, + { "%010.2lf", "-000001.#J", 0, DOUBLE_ARG, 0, 0, IND }, + { "%010.2lf", "0000001.#R", 0, DOUBLE_ARG, 0, 0, NAN }, + { "%010.2lf", "0000001.#J", 0, DOUBLE_ARG, 0, 0, INFINITY }, + { "%c", "a", 0, INT_ARG, 'a' }, + { "%c", "\x82", 0, INT_ARG, 0xa082 }, + { "%C", "a", 0, INT_ARG, 'a' }, + { "%C", "", 0, INT_ARG, 0x3042 }, + { "a%Cb", "ab", 0, INT_ARG, 0x3042 }, + { "%lld", "-8589934591", "1", ULONGLONG_ARG, 0, ((ULONGLONG)0xffffffff)*0xffffffff }, + { "%I32d", "1", "I32d", INT_ARG, 1 }, + { "%.0f", "-2", 0, DOUBLE_ARG, 0, 0, -1.5 }, + { "%.0f", "-1", 0, DOUBLE_ARG, 0, 0, -0.5 }, + { "%.0f", "1", 0, DOUBLE_ARG, 0, 0, 0.5 }, + { "%.0f", "2", 0, DOUBLE_ARG, 0, 0, 1.5 }, + { "%.30f", "0.333333333333333310000000000000", 0, TODO_FLAG | DOUBLE_ARG, 0, 0, 1.0/3.0 }, + { "%.30lf", "1.414213562373095100000000000000", 0, TODO_FLAG | DOUBLE_ARG, 0, 0, sqrt(2) }, + { "%f", "3.141593", 0, DOUBLE_ARG, 0, 0, 3.141592653590000 }, + { "%.10f", "3.1415926536", 0, DOUBLE_ARG, 0, 0, 3.141592653590000 }, + { "%.11f", "3.14159265359", 0, DOUBLE_ARG, 0, 0, 3.141592653590000 }, + { "%.15f", "3.141592653590000", 0, DOUBLE_ARG, 0, 0, 3.141592653590000 }, + { "%.15f", "3.141592653589793", 0, DOUBLE_ARG, 0, 0, M_PI }, + { "%.13f", "37.8662615745371", 0, DOUBLE_ARG, 0, 0, 37.866261574537077 }, + { "%.14f", "37.86626157453708", 0, DOUBLE_ARG, 0, 0, 37.866261574537077 }, + { "%.15f", "37.866261574537077", 0, DOUBLE_ARG, 0, 0, 37.866261574537077 }, + { "%g", "0.0005", 0, DOUBLE_ARG, 0, 0, 0.0005 }, + { "%g", "5e-005", 0, DOUBLE_ARG, 0, 0, 0.00005 }, + { "%g", "5e-006", 0, DOUBLE_ARG, 0, 0, 0.000005 }, + { "%g", "1e+015", 0, DOUBLE_ARG, 0, 0, 999999999999999.0 }, + { "%g", "1e+015", 0, DOUBLE_ARG, 0, 0, 1000000000000000.0 }, + { "%.15g", "0.0005", 0, DOUBLE_ARG, 0, 0, 0.0005 }, + { "%.15g", "5e-005", 0, DOUBLE_ARG, 0, 0, 0.00005 }, + { "%.15g", "5e-006", 0, DOUBLE_ARG, 0, 0, 0.000005 }, + { "%.15g", "999999999999999", 0, DOUBLE_ARG, 0, 0, 999999999999999.0 }, + { "%.15g", "1e+015", 0, DOUBLE_ARG, 0, 0, 1000000000000000.0 }, + }; - format = "%I0d"; - r = p_sprintf(buffer,format,1); - ok(!strcmp(buffer,"I0d"),"I0d failed\n"); - ok( r==3, "return count wrong\n"); + char buffer[100]; + int i, x, r; + + for (i=0; i<ARRAY_SIZE(tests); i++) { + memset(buffer, 'x', sizeof(buffer)); + switch(tests[i].type & 0xff) { + case NO_ARG: + r = p_sprintf(buffer, tests[i].format); + break; + case INT_ARG: + r = p_sprintf(buffer, tests[i].format, tests[i].arg_i); + break; + case ULONGLONG_ARG: + r = p_sprintf(buffer, tests[i].format, tests[i].arg_ull); + break; + case DOUBLE_ARG: + r = p_sprintf(buffer, tests[i].format, tests[i].arg_d); + break; + case PTR_ARG: + r = p_sprintf(buffer, tests[i].format, tests[i].arg_ptr); + break; + default: + ok(0, "tests[%d].type = %x\n", i, tests[i].type); + continue; + } - format = "%I32d"; - r = p_sprintf(buffer,format,1); - if (r == 1) - { - ok(!strcmp(buffer,"1"),"I32d failed, got '%s'\n",buffer); - } - else - { - /* Older versions don't grok I32 format */ - ok(r == 4 && !strcmp(buffer,"I32d"),"I32d failed, got '%s',%d\n",buffer,r); + ok(r == strlen(buffer), "%d) r = %d, buffer = \"%s\"\n", i, r, buffer); + todo_wine_if(tests[i].type & TODO_FLAG) + { + ok(!strcmp(buffer, tests[i].out) || + broken(tests[i].broken && !strcmp(buffer, tests[i].broken)), + "%d) buffer = \"%s\"\n", i, buffer); + } } - format = "%I64D"; - r = p_sprintf(buffer,format,(LONGLONG)-1); - ok(!strcmp(buffer,"D"),"I64D failed: %s\n",buffer); - ok( r==1, "return count wrong\n"); - - format = "%zx"; - r = p_sprintf(buffer,format,1); - ok(!strcmp(buffer, "zx"), "Problem with \"z\" interpretation\n"); - ok( r==2, "return count wrong\n"); - - format = "% d"; - r = p_sprintf(buffer,format,1); - ok(!strcmp(buffer, " 1"),"Problem with sign place-holder: '%s'\n",buffer); - ok( r==2, "return count wrong\n"); - - format = "%+ d"; - r = p_sprintf(buffer,format,1); - ok(!strcmp(buffer, "+1"),"Problem with sign flags: '%s'\n",buffer); - ok( r==2, "return count wrong\n"); - - format = "%S"; - r = p_sprintf(buffer,format,wide); - ok(!strcmp(buffer,"wide"),"Problem with wide string format\n"); - ok( r==4, "return count wrong\n"); - - format = "%04c"; - r = p_sprintf(buffer,format,'1'); - ok(!strcmp(buffer,"0001"),"Character not zero-prefixed \"%s\"\n",buffer); - ok( r==4, "return count wrong\n"); - - format = "%-04c"; - r = p_sprintf(buffer,format,'1'); - ok(!strcmp(buffer,"1 "),"Character zero-padded and/or not left-adjusted \"%s\"\n",buffer); - ok( r==4, "return count wrong\n"); - - format = "%#012x"; - r = p_sprintf(buffer,format,1); - ok(!strcmp(buffer,"0x0000000001"),"Hexadecimal zero-padded \"%s\"\n",buffer); - ok( r==12, "return count wrong\n"); - - r = p_sprintf(buffer,format,0); - ok(!strcmp(buffer,"000000000000"),"Hexadecimal zero-padded \"%s\"\n",buffer); - ok( r==12, "return count wrong\n"); - - format = "%#04.8x"; - r = p_sprintf(buffer,format,1); - ok(!strcmp(buffer,"0x00000001"), "Hexadecimal zero-padded precision \"%s\"\n",buffer); - ok( r==10, "return count wrong\n"); - - r = p_sprintf(buffer,format,0); - ok(!strcmp(buffer,"00000000"), "Hexadecimal zero-padded precision \"%s\"\n",buffer); - ok( r==8, "return count wrong\n"); - - format = "%#-08.2x"; - r = p_sprintf(buffer,format,1); - ok(!strcmp(buffer,"0x01 "), "Hexadecimal zero-padded not left-adjusted \"%s\"\n",buffer); - ok( r==8, "return count wrong\n"); - - r = p_sprintf(buffer,format,0); - ok(!strcmp(buffer,"00 "), "Hexadecimal zero-padded not left-adjusted \"%s\"\n",buffer); - ok( r==8, "return count wrong\n"); - - format = "%#.0x"; - r = p_sprintf(buffer,format,1); - ok(!strcmp(buffer,"0x1"), "Hexadecimal zero-padded zero-precision \"%s\"\n",buffer); - ok( r==3, "return count wrong\n"); - - r = p_sprintf(buffer,format,0); - ok(!strcmp(buffer,""), "Hexadecimal zero-padded zero-precision \"%s\"\n",buffer); - ok( r==0, "return count wrong\n"); - - format = "%#08o"; - r = p_sprintf(buffer,format,1); - ok(!strcmp(buffer,"00000001"), "Octal zero-padded \"%s\"\n",buffer); - ok( r==8, "return count wrong\n"); - - format = "%#o"; - r = p_sprintf(buffer,format,1); - ok(!strcmp(buffer,"01"), "Octal zero-padded \"%s\"\n",buffer); - ok( r==2, "return count wrong\n"); - - r = p_sprintf(buffer,format,0); - ok(!strcmp(buffer,"0"), "Octal zero-padded \"%s\"\n",buffer); - ok( r==1, "return count wrong\n"); - if (sizeof(void *) == 8) { - format = "%p"; - r = p_sprintf(buffer,format,(void *)57); + r = p_sprintf(buffer, "%p", (void *)57); ok(!strcmp(buffer,"0000000000000039"),"Pointer formatted incorrectly \"%s\"\n",buffer); ok( r==16, "return count wrong\n"); - format = "%#020p"; - r = p_sprintf(buffer,format,(void *)57); + r = p_sprintf(buffer, "%#020p", (void *)57); ok(!strcmp(buffer," 0X0000000000000039"),"Pointer formatted incorrectly\n"); ok( r==20, "return count wrong\n"); - format = "%Fp"; - r = p_sprintf(buffer,format,(void *)57); + r = p_sprintf(buffer, "%Fp", (void *)57); ok(!strcmp(buffer,"0000000000000039"),"Pointer formatted incorrectly \"%s\"\n",buffer); ok( r==16, "return count wrong\n"); - format = "%Np"; - r = p_sprintf(buffer,format,(void *)57); + r = p_sprintf(buffer, "%Np", (void *)57); ok(!strcmp(buffer,"0000000000000039"),"Pointer formatted incorrectly \"%s\"\n",buffer); ok( r==16, "return count wrong\n"); - format = "%#-020p"; - r = p_sprintf(buffer,format,(void *)57); + r = p_sprintf(buffer, "%#-020p", (void *)57); ok(!strcmp(buffer,"0X0000000000000039 "),"Pointer formatted incorrectly\n"); ok( r==20, "return count wrong\n"); - format = "%Ix %d"; - r = p_sprintf(buffer,format,(size_t)0x12345678123456,1); + r = p_sprintf(buffer, "%Ix %d", (size_t)0x12345678123456,1); ok(!strcmp(buffer,"12345678123456 1"),"buffer = %s\n",buffer); ok( r==16, "return count wrong\n"); + + r = p_sprintf(buffer, "%p", 0); + ok(!strcmp(buffer,"0000000000000000"), "failed\n"); + ok( r==16, "return count wrong\n"); } else { - format = "%p"; - r = p_sprintf(buffer,format,(void *)57); + r = p_sprintf(buffer, "%p", (void *)57); ok(!strcmp(buffer,"00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer); ok( r==8, "return count wrong\n"); - format = "%#012p"; - r = p_sprintf(buffer,format,(void *)57); + r = p_sprintf(buffer, "%#012p", (void *)57); ok(!strcmp(buffer," 0X00000039"),"Pointer formatted incorrectly\n"); ok( r==12, "return count wrong\n"); - format = "%Fp"; - r = p_sprintf(buffer,format,(void *)57); + r = p_sprintf(buffer, "%Fp", (void *)57); ok(!strcmp(buffer,"00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer); ok( r==8, "return count wrong\n"); - format = "%Np"; - r = p_sprintf(buffer,format,(void *)57); + r = p_sprintf(buffer, "%Np",(void *)57); ok(!strcmp(buffer,"00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer); ok( r==8, "return count wrong\n"); - format = "%#-012p"; - r = p_sprintf(buffer,format,(void *)57); + r = p_sprintf(buffer, "%#-012p", (void *)57); ok(!strcmp(buffer,"0X00000039 "),"Pointer formatted incorrectly\n"); ok( r==12, "return count wrong\n"); - format = "%Ix %d"; - r = p_sprintf(buffer,format,0x123456,1); + r = p_sprintf(buffer, "%Ix %d", 0x123456, 1); ok(!strcmp(buffer,"123456 1"),"buffer = %s\n",buffer); ok( r==8, "return count wrong\n"); - } - format = "%04s"; - r = p_sprintf(buffer,format,"foo"); - ok(!strcmp(buffer,"0foo"),"String not zero-prefixed \"%s\"\n",buffer); - ok( r==4, "return count wrong\n"); - - format = "%.1s"; - r = p_sprintf(buffer,format,"foo"); - ok(!strcmp(buffer,"f"),"Precision ignored \"%s\"\n",buffer); - ok( r==1, "return count wrong\n"); + r = p_sprintf(buffer, "%p", 0); + ok(!strcmp(buffer,"00000000"), "failed\n"); + ok( r==8, "return count wrong\n"); + } - format = "%.*s"; - r = p_sprintf(buffer,format,1,"foo"); + r = p_sprintf(buffer, "%.*s", 1, "foo"); ok(!strcmp(buffer,"f"),"Precision ignored \"%s\"\n",buffer); ok( r==1, "return count wrong\n"); - format = "%*s"; - r = p_sprintf(buffer,format,-5,"foo"); + r = p_sprintf(buffer, "%*s", -5, "foo"); ok(!strcmp(buffer,"foo "),"Negative field width ignored \"%s\"\n",buffer); ok( r==5, "return count wrong\n"); - format = "hello"; - r = p_sprintf(buffer, format); - ok(!strcmp(buffer,"hello"), "failed\n"); - ok( r==5, "return count wrong\n"); - - format = "%ws"; - r = p_sprintf(buffer, format, wide); - ok(!strcmp(buffer,"wide"), "failed\n"); - ok( r==4, "return count wrong\n"); - - format = "%-10ws"; - r = p_sprintf(buffer, format, wide ); - ok(!strcmp(buffer,"wide "), "failed\n"); - ok( r==10, "return count wrong\n"); - - format = "%10ws"; - r = p_sprintf(buffer, format, wide ); - ok(!strcmp(buffer," wide"), "failed\n"); - ok( r==10, "return count wrong\n"); - - format = "%#+ -03whlls"; - r = p_sprintf(buffer, format, wide ); - ok(!strcmp(buffer,"wide"), "failed\n"); - ok( r==4, "return count wrong\n"); - - format = "%w0s"; - r = p_sprintf(buffer, format, wide ); - ok(!strcmp(buffer,"0s"), "failed\n"); - ok( r==2, "return count wrong\n"); - - format = "%w-s"; - r = p_sprintf(buffer, format, wide ); - ok(!strcmp(buffer,"-s"), "failed\n"); - ok( r==2, "return count wrong\n"); - - format = "%ls"; - r = p_sprintf(buffer, format, wide ); - ok(!strcmp(buffer,"wide"), "failed\n"); - ok( r==4, "return count wrong\n"); - - format = "%Ls"; - r = p_sprintf(buffer, format, "not wide" ); - ok(!strcmp(buffer,"not wide"), "failed\n"); - ok( r==8, "return count wrong\n"); - - format = "%b"; - r = p_sprintf(buffer, format); - ok(!strcmp(buffer,"b"), "failed\n"); - ok( r==1, "return count wrong\n"); - - format = "%3c"; - r = p_sprintf(buffer, format,'a'); - ok(!strcmp(buffer," a"), "failed\n"); - ok( r==3, "return count wrong\n"); - - format = "%3d"; - r = p_sprintf(buffer, format,1234); - ok(!strcmp(buffer,"1234"), "failed\n"); - ok( r==4, "return count wrong\n"); - - format = "%3h"; - r = p_sprintf(buffer, format); - ok(!strcmp(buffer,""), "failed\n"); - ok( r==0, "return count wrong\n"); - - format = "%j%k%m%q%r%t%v%y%z"; - r = p_sprintf(buffer, format); - ok(!strcmp(buffer,"jkmqrtvyz"), "failed\n"); - ok( r==9, "return count wrong\n"); - - format = "asdf%n"; x = 0; - r = p_sprintf(buffer, format, &x ); + r = p_sprintf(buffer, "asdf%n", &x ); if (r == -1) { /* %n format is disabled by default on vista */ @@ -583,228 +392,7 @@ static void test_sprintf( void ) ok( r==4, "return count wrong: %d\n", r); } - format = "%-1d"; - r = p_sprintf(buffer, format,2); - ok(!strcmp(buffer,"2"), "failed\n"); - ok( r==1, "return count wrong\n"); - - format = "%2.4f"; - r = p_sprintf(buffer, format,8.6); - ok(!strcmp(buffer,"8.6000"), "failed\n"); - ok( r==6, "return count wrong\n"); - - format = "%0f"; - r = p_sprintf(buffer, format,0.6); - ok(!strcmp(buffer,"0.600000"), "failed\n"); - ok( r==8, "return count wrong\n"); - - format = "%.0f"; - r = p_sprintf(buffer, format,0.6); - ok(!strcmp(buffer,"1"), "failed\n"); - ok( r==1, "return count wrong\n"); - - format = "%2.4e"; - r = p_sprintf(buffer, format,8.6); - ok(!strcmp(buffer,"8.6000e+000"), "failed\n"); - ok( r==11, "return count wrong\n"); - - format = "% 2.4e"; - r = p_sprintf(buffer, format,8.6); - ok(!strcmp(buffer," 8.6000e+000"), "failed: %s\n", buffer); - ok( r==12, "return count wrong\n"); - - format = "% 014.4e"; - r = p_sprintf(buffer, format,8.6); - ok(!strcmp(buffer," 008.6000e+000"), "failed: %s\n", buffer); - ok( r==14, "return count wrong\n"); - - format = "% 2.4e"; - r = p_sprintf(buffer, format,-8.6); - ok(!strcmp(buffer,"-8.6000e+000"), "failed: %s\n", buffer); - ok( r==12, "return count wrong\n"); - - format = "%+2.4e"; - r = p_sprintf(buffer, format,8.6); - ok(!strcmp(buffer,"+8.6000e+000"), "failed: %s\n", buffer); - ok( r==12, "return count wrong\n"); - - format = "%2.4g"; - r = p_sprintf(buffer, format,8.6); - ok(!strcmp(buffer,"8.6"), "failed\n"); - ok( r==3, "return count wrong\n"); - - format = "%-i"; - r = p_sprintf(buffer, format,-1); - ok(!strcmp(buffer,"-1"), "failed\n"); - ok( r==2, "return count wrong\n"); - - format = "%-i"; - r = p_sprintf(buffer, format,1); - ok(!strcmp(buffer,"1"), "failed\n"); - ok( r==1, "return count wrong\n"); - - format = "%+i"; - r = p_sprintf(buffer, format,1); - ok(!strcmp(buffer,"+1"), "failed\n"); - ok( r==2, "return count wrong\n"); - - format = "%o"; - r = p_sprintf(buffer, format,10); - ok(!strcmp(buffer,"12"), "failed\n"); - ok( r==2, "return count wrong\n"); - - format = "%p"; - r = p_sprintf(buffer, format,0); - if (sizeof(void *) == 8) - { - ok(!strcmp(buffer,"0000000000000000"), "failed\n"); - ok( r==16, "return count wrong\n"); - } - else - { - ok(!strcmp(buffer,"00000000"), "failed\n"); - ok( r==8, "return count wrong\n"); - } - - format = "%s"; - r = p_sprintf(buffer, format,0); - ok(!strcmp(buffer,"(null)"), "failed\n"); - ok( r==6, "return count wrong\n"); - - format = "%s"; - r = p_sprintf(buffer, format,"%%%%"); - ok(!strcmp(buffer,"%%%%"), "failed\n"); - ok( r==4, "return count wrong\n"); - - format = "%u"; - r = p_sprintf(buffer, format,-1); - ok(!strcmp(buffer,"4294967295"), "failed\n"); - ok( r==10, "return count wrong\n"); - - format = "%w"; - r = p_sprintf(buffer, format,-1); - ok(!strcmp(buffer,""), "failed\n"); - ok( r==0, "return count wrong\n"); - - format = "%h"; - r = p_sprintf(buffer, format,-1); - ok(!strcmp(buffer,""), "failed\n"); - ok( r==0, "return count wrong\n"); - - format = "%z"; - r = p_sprintf(buffer, format,-1); - ok(!strcmp(buffer,"z"), "failed\n"); - ok( r==1, "return count wrong\n"); - - format = "%j"; - r = p_sprintf(buffer, format,-1); - ok(!strcmp(buffer,"j"), "failed\n"); - ok( r==1, "return count wrong\n"); - - format = "%F"; - r = p_sprintf(buffer, format,-1); - ok(!strcmp(buffer,""), "failed\n"); - ok( r==0, "return count wrong\n"); - - format = "%N"; - r = p_sprintf(buffer, format,-1); - ok(!strcmp(buffer,""), "failed\n"); - ok( r==0, "return count wrong\n"); - - format = "%H"; - r = p_sprintf(buffer, format,-1); - ok(!strcmp(buffer,"H"), "failed\n"); - ok( r==1, "return count wrong\n"); - - format = "x%cx"; - r = p_sprintf(buffer, format, 0x100+'X'); - ok(!strcmp(buffer,"xXx"), "failed\n"); - ok( r==3, "return count wrong\n"); - - format = "%%0"; - r = p_sprintf(buffer, format); - ok(!strcmp(buffer,"%0"), "failed: \"%s\"\n", buffer); - ok( r==2, "return count wrong\n"); - - format = "%hx"; - r = p_sprintf(buffer, format, 0x12345); - ok(!strcmp(buffer,"2345"), "failed \"%s\"\n", buffer); - - format = "%hhx"; - r = p_sprintf(buffer, format, 0x123); - ok(!strcmp(buffer,"123"), "failed: \"%s\"\n", buffer); - r = p_sprintf(buffer, format, 0x12345); - ok(!strcmp(buffer,"2345"), "failed \"%s\"\n", buffer); - - format = "%lf"; - r = p_sprintf(buffer, format, IND); - ok(r==9, "r = %d\n", r); - ok(!strcmp(buffer, "-1.#IND00"), "failed: \"%s\"\n", buffer); - r = p_sprintf(buffer, format, NAN); - ok(r==8, "r = %d\n", r); - ok(!strcmp(buffer, "1.#QNAN0"), "failed: \"%s\"\n", buffer); - r = p_sprintf(buffer, format, INFINITY); - ok(r==8, "r = %d\n", r); - ok(!strcmp(buffer, "1.#INF00"), "failed: \"%s\"\n", buffer); - - format = "%le"; - r = p_sprintf(buffer, format, IND); - ok(r==14, "r = %d\n", r); - ok(!strcmp(buffer, "-1.#IND00e+000"), "failed: \"%s\"\n", buffer); - r = p_sprintf(buffer, format, NAN); - ok(r==13, "r = %d\n", r); - ok(!strcmp(buffer, "1.#QNAN0e+000"), "failed: \"%s\"\n", buffer); - r = p_sprintf(buffer, format, INFINITY); - ok(r==13, "r = %d\n", r); - ok(!strcmp(buffer, "1.#INF00e+000"), "failed: \"%s\"\n", buffer); - - format = "%lg"; - r = p_sprintf(buffer, format, IND); - ok(r==7, "r = %d\n", r); - ok(!strcmp(buffer, "-1.#IND"), "failed: \"%s\"\n", buffer); - r = p_sprintf(buffer, format, NAN); - ok(r==7, "r = %d\n", r); - ok(!strcmp(buffer, "1.#QNAN"), "failed: \"%s\"\n", buffer); - r = p_sprintf(buffer, format, INFINITY); - ok(r==6, "r = %d\n", r); - ok(!strcmp(buffer, "1.#INF"), "failed: \"%s\"\n", buffer); - - format = "%010.2lf"; - r = p_sprintf(buffer, format, IND); - ok(r==10, "r = %d\n", r); - ok(!strcmp(buffer, "-000001.#J"), "failed: \"%s\"\n", buffer); - r = p_sprintf(buffer, format, NAN); - ok(r==10, "r = %d\n", r); - ok(!strcmp(buffer, "0000001.#R"), "failed: \"%s\"\n", buffer); - r = p_sprintf(buffer, format, INFINITY); - ok(r==10, "r = %d\n", r); - ok(!strcmp(buffer, "0000001.#J"), "failed: \"%s\"\n", buffer); - - format = "%c"; - r = p_sprintf(buffer, format, 'a'); - ok(r==1, "r = %d\n", r); - ok(!strcmp(buffer, "a"), "failed: \"%s\"\n", buffer); - r = p_sprintf(buffer, format, 0xa082); - ok(r==1, "r = %d\n", r); - ok(!strcmp(buffer, "\x82"), "failed: \"%s\"\n", buffer); - - format = "%C"; - r = p_sprintf(buffer, format, 'a'); - ok(r==1, "r = %d\n", r); - ok(!strcmp(buffer, "a"), "failed: \"%s\"\n", buffer); - r = p_sprintf(buffer, format, 0x3042); - ok(r==0, "r = %d\n", r); - ok(!strcmp(buffer, ""), "failed: \"%s\"\n", buffer); - - format = "a%Cb"; - r = p_sprintf(buffer, format, 0x3042); - ok(r==2, "r = %d\n", r); - ok(!strcmp(buffer, "ab"), "failed: \"%s\"\n", buffer); - - format = "%S"; - buf_w[0] = 0x3042; - buf_w[1] = 0; - r = p_sprintf(buffer, format, buf_w); + r = p_sprintf(buffer, "%S", L"\x3042"); ok(r==-1 || broken(!r), "r = %d\n", r); if(!setlocale(LC_ALL, "Japanese_Japan.932")) { @@ -812,13 +400,11 @@ static void test_sprintf( void ) return; } - format = "%c"; - r = p_sprintf(buffer, format, 0xa082); + r = p_sprintf(buffer, "%c", 0xa082); ok(r==1, "r = %d\n", r); ok(!strcmp(buffer, "\x82"), "failed: \"%s\"\n", buffer); - format = "%C"; - r = p_sprintf(buffer, format, 0x3042); + r = p_sprintf(buffer, "%C", 0x3042); ok(r==2, "r = %d\n", r); ok(!strcmp(buffer, "\x82\xa0"), "failed: \"%s\"\n", buffer); @@ -828,28 +414,34 @@ static void test_sprintf( void ) ok(!strcmp(buffer, "string to copy"), "failed: \"%s\"\n", buffer); setlocale(LC_ALL, "C"); + + r = p_sprintf(buffer, "%*1d", 1, 3); + ok(r==11, "r = %d\n", r); + ok(!strcmp(buffer, " 3"), "failed: \"%s\"\n", buffer); + + r = p_sprintf(buffer, "%0*0d", 1, 2); + ok(r==10, "r = %d\n", r); + ok(!strcmp(buffer, "0000000002"), "failed: \"%s\"\n", buffer); + + r = p_sprintf(buffer, "% *2d", 0, 7); + ok(r==2, "r = %d\n", r); + ok(!strcmp(buffer, " 7"), "failed: \"%s\"\n", buffer); } static void test_swprintf( void ) { wchar_t buffer[100]; - const wchar_t I64d[] = {'%','I','6','4','d',0}; - double pnumber=789456123; - const wchar_t TwentyThreePoint15e[]= {'%','+','#','2','3','.','1','5','e',0}; - const wchar_t e008[] = {'e','+','0','0','8',0}; - const wchar_t string_w[] = {'s','t','r','i','n','g',0}; + double pnumber = 789456123; const char string[] = "string"; - const wchar_t S[]={'%','S',0}; - const wchar_t hs[] = {'%', 'h', 's', 0}; - - swprintf(buffer,TwentyThreePoint15e,pnumber); - ok(wcsstr(buffer,e008) != 0,"Sprintf different\n"); - swprintf(buffer,I64d,((ULONGLONG)0xffffffff)*0xffffffff); - ok(wcslen(buffer) == 11,"Problem with long long\n"); - swprintf(buffer,S,string); - ok(wcslen(buffer) == 6,"Problem with \"%%S\" interpretation\n"); - swprintf(buffer, hs, string); - ok( wcscmp(string_w,buffer) == 0, "swprintf failed with %%hs\n"); + + swprintf(buffer, L"%+#23.15e", pnumber); + ok(wcsstr(buffer, L"e+008") != 0, "Sprintf different\n"); + swprintf(buffer, L"%I64d", ((ULONGLONG)0xffffffff)*0xffffffff); + ok(wcslen(buffer) == 11, "Problem with long long\n"); + swprintf(buffer, L"%S", string); + ok(wcslen(buffer) == 6, "Problem with \"%%S\" interpretation\n"); + swprintf(buffer, L"%hs", string); + ok(!wcscmp(L"string", buffer), "swprintf failed with %%hs\n"); } static void test_snprintf (void) @@ -867,10 +459,12 @@ static void test_snprintf (void) const int bufsiz = sizeof buffer; unsigned int i; + int (__cdecl *p_snprintf)(char*,size_t,const char*,...) = _snprintf; + for (i = 0; i < ARRAY_SIZE(tests); i++) { const char *fmt = tests[i].format; const int expect = tests[i].expected; - const int n = _snprintf (buffer, bufsiz, fmt); + const int n = p_snprintf(buffer, bufsiz, fmt); const int valid = n < 0 ? bufsiz : (n == bufsiz ? n : n+1); ok (n == expect, "\"%s\": expected %d, returned %d\n", @@ -882,10 +476,7 @@ static void test_snprintf (void) static void test_fprintf(void) { - static const char file_name[] = "fprintf.tst"; - static const WCHAR utf16_test[] = {'u','n','i','c','o','d','e','\n',0}; - - FILE *fp = fopen(file_name, "wb"); + FILE *fp = fopen("fprintf.tst", "wb"); char buf[1024]; int ret; @@ -899,14 +490,14 @@ static void test_fprintf(void) ret = ftell(fp); ok(ret == 26, "ftell returned %d\n", ret); - ret = fwprintf(fp, utf16_test); + ret = fwprintf(fp, L"unicode\n"); ok(ret == 8, "ret = %d\n", ret); ret = ftell(fp); ok(ret == 42, "ftell returned %d\n", ret); fclose(fp); - fp = fopen(file_name, "rb"); + fp = fopen("fprintf.tst", "rb"); ret = fscanf(fp, "%[^\n] ", buf); ok(ret == 1, "ret = %d\n", ret); ret = ftell(fp); @@ -922,12 +513,11 @@ static void test_fprintf(void) fgets(buf, sizeof(buf), fp); ret = ftell(fp); ok(ret == 41, "ret = %d\n", ret); - ok(!memcmp(buf, utf16_test, sizeof(utf16_test)), - "buf = %s\n", wine_dbgstr_w((WCHAR*)buf)); + ok(!wcscmp((wchar_t*)buf, L"unicode\n"), "buf = %s\n", wine_dbgstr_w((WCHAR*)buf)); fclose(fp); - fp = fopen(file_name, "wt"); + fp = fopen("fprintf.tst", "wt"); ret = fprintf(fp, "simple test\n"); ok(ret == 12, "ret = %d\n", ret); @@ -939,14 +529,14 @@ static void test_fprintf(void) ret = ftell(fp); ok(ret == 28, "ftell returned %d\n", ret); - ret = fwprintf(fp, utf16_test); + ret = fwprintf(fp, L"unicode\n"); ok(ret == 8, "ret = %d\n", ret); ret = ftell(fp); ok(ret == 37, "ftell returned %d\n", ret); fclose(fp); - fp = fopen(file_name, "rb"); + fp = fopen("fprintf.tst", "rb"); ret = fscanf(fp, "%[^\n] ", buf); ok(ret == 1, "ret = %d\n", ret); ret = ftell(fp); @@ -964,7 +554,7 @@ static void test_fprintf(void) ok(!strcmp(buf, "unicode\r\n"), "buf = %s\n", buf); fclose(fp); - unlink(file_name); + unlink("fprintf.tst"); } static void test_fcvt(void) @@ -1076,27 +666,23 @@ static struct { int expsign; } test_cvt_testcases[] = { { 45.0, 2, "45", "4500", 2, 2, 0 }, - /* Numbers less than 1.0 with different precisions */ { 0.0001, 1, "1", "", -3, -3, 0 }, { 0.0001, 10,"1000000000", "1000000", -3, -3, 0 }, - /* Basic sign test */ { -111.0001, 5, "11100", "11100010", 3, 3, 1 }, { 111.0001, 5, "11100", "11100010", 3, 3, 0 }, - /* big numbers with low precision */ { 3333.3, 2, "33", "333330", 4, 4, 0 }, {999999999999.9, 3, "100","999999999999900", 13, 12, 0 }, - /* 0.0 with different precisions */ { 0.0, 5, "00000", "00000", 0, 0, 0 }, { 0.0, 0, "", "", 0, 0, 0 }, { 0.0, -1, "", "", 0, 0, 0 }, - /* Numbers > 1.0 with 0 or -ve precision */ + { -0.0, 5, "00000", "00000", 0, 0, 1 }, + { -0.0, 0, "", "", 0, 0, 1 }, + { -0.0, -1, "", "", 0, 0, 1 }, { -123.0001, 0, "", "123", 3, 3, 1 }, { -123.0001, -1, "", "12", 3, 3, 1 }, { -123.0001, -2, "", "1", 3, 3, 1 }, { -123.0001, -3, "", "", 3, 3, 1 }, - /* Numbers > 1.0, but with rounding at the point of precision */ { 99.99, 1, "1", "1000", 3, 3, 0 }, - /* Numbers < 1.0 where rounding occurs at the point of precision */ { 0.0063, 2, "63", "1", -2, -1, 0 }, { 0.0063, 3, "630", "6", -2, -2, 0 }, { 0.09999999996, 2, "10", "10", 0, 0, 0 }, @@ -1105,12 +691,18 @@ static struct { { 0.4, 0, "", "", 0, 0, 0 }, { 0.49, 0, "", "", 0, 0, 0 }, { 0.51, 0, "", "1", 1, 1, 0 }, - /* ask for ridiculous precision, ruin formatting this table */ + { NAN, 2, "1$", "1#R", 1, 1, 0 }, + { NAN, 5, "1#QNB", "1#QNAN", 1, 1, 0 }, + { -NAN, 2, "1$", "1#J", 1, 1, 1 }, + { -NAN, 5, "1#IND", "1#IND0", 1, 1, 1 }, + { INFINITY, 2, "1$", "1#J", 1, 1, 0 }, + { INFINITY, 5, "1#INF", "1#INF0", 1, 1, 0 }, + { -INFINITY, 2, "1$", "1#J", 1, 1, 1 }, + { -INFINITY, 5, "1#INF", "1#INF0", 1, 1, 1 }, { 1.0, 30, "100000000000000000000000000000", "1000000000000000000000000000000", 1, 1, 0}, { 123456789012345678901.0, 30, "123456789012345680000000000000", "123456789012345680000000000000000000000000000000000", 21, 21, 0}, - /* end marker */ { 0, 0, "END"} }; @@ -1125,14 +717,14 @@ static void test_xcvt(void) test_cvt_testcases[i].nrdigits, &decpt, &sign); - ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_e, 15), - "_ecvt() bad return, got \n'%s' expected \n'%s'\n", str, + ok( !strncmp( str, test_cvt_testcases[i].expstr_e, 15), + "%d) _ecvt() bad return, got '%s' expected '%s'\n", i, str, test_cvt_testcases[i].expstr_e); ok( decpt == test_cvt_testcases[i].expdecpt_e, - "_ecvt() decimal point wrong, got %d expected %d\n", decpt, + "%d) _ecvt() decimal point wrong, got %d expected %d\n", i, decpt, test_cvt_testcases[i].expdecpt_e); ok( sign == test_cvt_testcases[i].expsign, - "_ecvt() sign wrong, got %d expected %d\n", sign, + "%d) _ecvt() sign wrong, got %d expected %d\n", i, sign, test_cvt_testcases[i].expsign); } for( i = 0; strcmp( test_cvt_testcases[i].expstr_e, "END"); i++){ @@ -1141,14 +733,14 @@ static void test_xcvt(void) test_cvt_testcases[i].nrdigits, &decpt, &sign); - ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_f, 15), - "_fcvt() bad return, got \n'%s' expected \n'%s'\n", str, + ok( !strncmp( str, test_cvt_testcases[i].expstr_f, 15), + "%d) _fcvt() bad return, got '%s' expected '%s'\n", i, str, test_cvt_testcases[i].expstr_f); ok( decpt == test_cvt_testcases[i].expdecpt_f, - "_fcvt() decimal point wrong, got %d expected %d\n", decpt, + "%d) _fcvt() decimal point wrong, got %d expected %d\n", i, decpt, test_cvt_testcases[i].expdecpt_f); ok( sign == test_cvt_testcases[i].expsign, - "_fcvt() sign wrong, got %d expected %d\n", sign, + "%d) _fcvt() sign wrong, got %d expected %d\n", i, sign, test_cvt_testcases[i].expsign); } @@ -1159,14 +751,14 @@ static void test_xcvt(void) decpt = sign = 100; err = p__ecvt_s(str, 1024, test_cvt_testcases[i].value, test_cvt_testcases[i].nrdigits, &decpt, &sign); ok(err == 0, "_ecvt_s() failed with error code %d\n", err); - ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_e, 15), - "_ecvt_s() bad return, got \n'%s' expected \n'%s'\n", str, + ok( !strncmp( str, test_cvt_testcases[i].expstr_e, 15), + "%d) _ecvt_s() bad return, got '%s' expected '%s'\n", i, str, test_cvt_testcases[i].expstr_e); ok( decpt == test_cvt_testcases[i].expdecpt_e, - "_ecvt_s() decimal point wrong, got %d expected %d\n", decpt, + "%d) _ecvt_s() decimal point wrong, got %d expected %d\n", i, decpt, test_cvt_testcases[i].expdecpt_e); ok( sign == test_cvt_testcases[i].expsign, - "_ecvt_s() sign wrong, got %d expected %d\n", sign, + "%d) _ecvt_s() sign wrong, got %d expected %d\n", i, sign, test_cvt_testcases[i].expsign); } free(str); @@ -1203,15 +795,15 @@ static void test_xcvt(void) for( i = 0; strcmp( test_cvt_testcases[i].expstr_e, "END"); i++){ decpt = sign = 100; err = p__fcvt_s(str, 1024, test_cvt_testcases[i].value, test_cvt_testcases[i].nrdigits, &decpt, &sign); - ok(err == 0, "_fcvt_s() failed with error code %d\n", err); - ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_f, 15), - "_fcvt_s() bad return, got '%s' expected '%s'. test %d\n", str, + ok(!err, "%d) _fcvt_s() failed with error code %d\n", i, err); + ok( !strncmp( str, test_cvt_testcases[i].expstr_f, 15), + "%d) _fcvt_s() bad return, got '%s' expected '%s'. test %d\n", i, str, test_cvt_testcases[i].expstr_f, i); ok( decpt == test_cvt_testcases[i].expdecpt_f, - "_fcvt_s() decimal point wrong, got %d expected %d\n", decpt, + "%d) _fcvt_s() decimal point wrong, got %d expected %d\n", i, decpt, test_cvt_testcases[i].expdecpt_f); ok( sign == test_cvt_testcases[i].expsign, - "_fcvt_s() sign wrong, got %d expected %d\n", sign, + "%d) _fcvt_s() sign wrong, got %d expected %d\n", i, sign, test_cvt_testcases[i].expsign); } free(str); @@ -1223,104 +815,94 @@ static void test_xcvt(void) static int WINAPIV _vsnwprintf_wrapper(wchar_t *str, size_t len, const wchar_t *format, ...) { int ret; - __ms_va_list valist; - __ms_va_start(valist, format); + va_list valist; + va_start(valist, format); ret = _vsnwprintf(str, len, format, valist); - __ms_va_end(valist); + va_end(valist); return ret; } static void test_vsnwprintf(void) { - const wchar_t format[] = {'%','w','s','%','w','s','%','w','s',0}; - const wchar_t one[] = {'o','n','e',0}; - const wchar_t two[] = {'t','w','o',0}; - const wchar_t three[] = {'t','h','r','e','e',0}; - int ret; wchar_t str[32]; char buf[32]; - ret = _vsnwprintf_wrapper( str, ARRAY_SIZE(str), format, one, two, three ); - + ret = _vsnwprintf_wrapper( str, ARRAY_SIZE(str), L"%ws%ws%ws", L"one", L"two", L"three" ); ok( ret == 11, "got %d expected 11\n", ret ); WideCharToMultiByte( CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL ); ok( !strcmp(buf, "onetwothree"), "got %s expected 'onetwothree'\n", buf ); - ret = _vsnwprintf_wrapper( str, 0, format, one, two, three ); + ret = _vsnwprintf_wrapper( str, 0, L"%ws%ws%ws", L"one", L"two", L"three" ); ok( ret == -1, "got %d, expected -1\n", ret ); - ret = _vsnwprintf_wrapper( NULL, 0, format, one, two, three ); + ret = _vsnwprintf_wrapper( NULL, 0, L"%ws%ws%ws", L"one", L"two", L"three" ); ok( ret == 11 || broken(ret == -1 /* Win2k */), "got %d, expected 11\n", ret ); } static int WINAPIV vswprintf_wrapper(wchar_t *str, const wchar_t *format, ...) { int ret; - __ms_va_list valist; - __ms_va_start(valist, format); + va_list valist; + va_start(valist, format); ret = p_vswprintf(str, format, valist); - __ms_va_end(valist); + va_end(valist); return ret; } static int WINAPIV _vswprintf_wrapper(wchar_t *str, const wchar_t *format, ...) { int ret; - __ms_va_list valist; - __ms_va_start(valist, format); + va_list valist; + va_start(valist, format); ret = p__vswprintf(str, format, valist); - __ms_va_end(valist); + va_end(valist); return ret; } static int WINAPIV _vswprintf_l_wrapper(wchar_t *str, const wchar_t *format, void *locale, ...) { int ret; - __ms_va_list valist; - __ms_va_start(valist, locale); + va_list valist; + va_start(valist, locale); ret = p__vswprintf_l(str, format, locale, valist); - __ms_va_end(valist); + va_end(valist); return ret; } static int WINAPIV _vswprintf_c_wrapper(wchar_t *str, size_t size, const wchar_t *format, ...) { int ret; - __ms_va_list valist; - __ms_va_start(valist, format); + va_list valist; + va_start(valist, format); ret = p__vswprintf_c(str, size, format, valist); - __ms_va_end(valist); + va_end(valist); return ret; } static int WINAPIV _vswprintf_c_l_wrapper(wchar_t *str, size_t size, const wchar_t *format, void *locale, ...) { int ret; - __ms_va_list valist; - __ms_va_start(valist, locale); + va_list valist; + va_start(valist, locale); ret = p__vswprintf_c_l(str, size, format, locale, valist); - __ms_va_end(valist); + va_end(valist); return ret; } static int WINAPIV _vswprintf_p_l_wrapper(wchar_t *str, size_t size, const wchar_t *format, void *locale, ...) { int ret; - __ms_va_list valist; - __ms_va_start(valist, locale); + va_list valist; + va_start(valist, locale); ret = p__vswprintf_p_l(str, size, format, locale, valist); - __ms_va_end(valist); + va_end(valist); return ret; } static void test_vswprintf(void) { - const wchar_t format[] = {'%','s',' ','%','d',0}; - const wchar_t number[] = {'n','u','m','b','e','r',0}; - const wchar_t out[] = {'n','u','m','b','e','r',' ','1','2','3',0}; wchar_t buf[20]; - int ret; if (!p_vswprintf || !p__vswprintf || !p__vswprintf_l ||!p__vswprintf_c @@ -1330,43 +912,48 @@ static void test_vswprintf(void) return; } - ret = vswprintf_wrapper(buf, format, number, 123); + ret = vswprintf_wrapper(buf, L"%s %d", L"number", 123); ok(ret == 10, "got %d, expected 10\n", ret); - ok(!memcmp(buf, out, sizeof(out)), "buf = %s\n", wine_dbgstr_w(buf)); + ok(!wcscmp(buf, L"number 123"), "buf = %s\n", wine_dbgstr_w(buf)); memset(buf, 0, sizeof(buf)); - ret = _vswprintf_wrapper(buf, format, number, 123); + ret = _vswprintf_wrapper(buf, L"%s %d", L"number", 123); ok(ret == 10, "got %d, expected 10\n", ret); - ok(!memcmp(buf, out, sizeof(out)), "buf = %s\n", wine_dbgstr_w(buf)); + ok(!wcscmp(buf, L"number 123"), "buf = %s\n", wine_dbgstr_w(buf)); memset(buf, 0, sizeof(buf)); - ret = _vswprintf_l_wrapper(buf, format, NULL, number, 123); + ret = _vswprintf_l_wrapper(buf, L"%s %d", NULL, L"number", 123); ok(ret == 10, "got %d, expected 10\n", ret); - ok(!memcmp(buf, out, sizeof(out)), "buf = %s\n", wine_dbgstr_w(buf)); + ok(!wcscmp(buf, L"number 123"), "buf = %s\n", wine_dbgstr_w(buf)); memset(buf, 0, sizeof(buf)); - ret = _vswprintf_c_wrapper(buf, 20, format, number, 123); + ret = _vswprintf_c_wrapper(buf, 20, L"%s %d", L"number", 123); ok(ret == 10, "got %d, expected 10\n", ret); - ok(!memcmp(buf, out, sizeof(out)), "buf = %s\n", wine_dbgstr_w(buf)); + ok(!wcscmp(buf, L"number 123"), "buf = %s\n", wine_dbgstr_w(buf)); + + memset(buf, 'x', sizeof(buf)); + ret = _vswprintf_c_wrapper(buf, 10, L"%s %d", L"number", 123); + ok(ret == -1, "got %d, expected -1\n", ret); + ok(!wcscmp(buf, L"number 12"), "buf = %s\n", wine_dbgstr_w(buf)); memset(buf, 0, sizeof(buf)); - ret = _vswprintf_c_l_wrapper(buf, 20, format, NULL, number, 123); + ret = _vswprintf_c_l_wrapper(buf, 20, L"%s %d", NULL, L"number", 123); ok(ret == 10, "got %d, expected 10\n", ret); - ok(!memcmp(buf, out, sizeof(out)), "buf = %s\n", wine_dbgstr_w(buf)); + ok(!wcscmp(buf, L"number 123"), "buf = %s\n", wine_dbgstr_w(buf)); memset(buf, 0, sizeof(buf)); - ret = _vswprintf_p_l_wrapper(buf, 20, format, NULL, number, 123); + ret = _vswprintf_p_l_wrapper(buf, 20, L"%s %d", NULL, L"number", 123); ok(ret == 10, "got %d, expected 10\n", ret); - ok(!memcmp(buf, out, sizeof(out)), "buf = %s\n", wine_dbgstr_w(buf)); + ok(!wcscmp(buf, L"number 123"), "buf = %s\n", wine_dbgstr_w(buf)); } static int WINAPIV _vscprintf_wrapper(const char *format, ...) { int ret; - __ms_va_list valist; - __ms_va_start(valist, format); + va_list valist; + va_start(valist, format); ret = p__vscprintf(format, valist); - __ms_va_end(valist); + va_end(valist); return ret; } @@ -1387,18 +974,15 @@ static void test_vscprintf(void) static int WINAPIV _vscwprintf_wrapper(const wchar_t *format, ...) { int ret; - __ms_va_list valist; - __ms_va_start(valist, format); + va_list valist; + va_start(valist, format); ret = p__vscwprintf(format, valist); - __ms_va_end(valist); + va_end(valist); return ret; } static void test_vscwprintf(void) { - const wchar_t format[] = {'%','s',' ','%','d',0}; - const wchar_t number[] = {'n','u','m','b','e','r',0}; - int ret; if (!p__vscwprintf) @@ -1407,7 +991,7 @@ static void test_vscwprintf(void) return; } - ret = _vscwprintf_wrapper( format, number, 1 ); + ret = _vscwprintf_wrapper(L"%s %d", L"number", 1 ); ok( ret == 8, "got %d expected 8\n", ret ); } @@ -1415,22 +999,17 @@ static int WINAPIV _vsnwprintf_s_wrapper(wchar_t *str, size_t sizeOfBuffer, size_t count, const wchar_t *format, ...) { int ret; - __ms_va_list valist; - __ms_va_start(valist, format); + va_list valist; + va_start(valist, format); ret = p__vsnwprintf_s(str, sizeOfBuffer, count, format, valist); - __ms_va_end(valist); + va_end(valist); return ret; } static void test_vsnwprintf_s(void) { - const wchar_t format[] = { 'A','B','%','u','C',0 }; - const wchar_t out7[] = { 'A','B','1','2','3','C',0 }; - const wchar_t out6[] = { 'A','B','1','2','3',0 }; - const wchar_t out2[] = { 'A',0 }; - const wchar_t out1[] = { 0 }; wchar_t buffer[14] = { 0 }; - int exp, got; + int ret; if (!p__vsnwprintf_s) { @@ -1439,44 +1018,40 @@ static void test_vsnwprintf_s(void) } /* Enough room. */ - exp = wcslen(out7); - - got = _vsnwprintf_s_wrapper(buffer, 14, _TRUNCATE, format, 123); - ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got); - ok( !wcscmp(out7, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer)); + ret = _vsnwprintf_s_wrapper(buffer, 14, _TRUNCATE, L"AB%uC", 123); + ok( ret == 6, "length wrong, expect=6, got=%d\n", ret); + ok( !wcscmp(L"AB123C", buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer)); - got = _vsnwprintf_s_wrapper(buffer, 12, _TRUNCATE, format, 123); - ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got); - ok( !wcscmp(out7, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer)); + ret = _vsnwprintf_s_wrapper(buffer, 12, _TRUNCATE, L"AB%uC", 123); + ok( ret == 6, "length wrong, expect=6, got=%d\n", ret); + ok( !wcscmp(L"AB123C", buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer)); - got = _vsnwprintf_s_wrapper(buffer, 7, _TRUNCATE, format, 123); - ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got); - ok( !wcscmp(out7, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer)); + ret = _vsnwprintf_s_wrapper(buffer, 7, _TRUNCATE, L"AB%uC", 123); + ok( ret == 6, "length wrong, expect=6, got=%d\n", ret); + ok( !wcscmp(L"AB123C", buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer)); /* Not enough room. */ - exp = -1; - - got = _vsnwprintf_s_wrapper(buffer, 6, _TRUNCATE, format, 123); - ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got); - ok( !wcscmp(out6, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer)); + ret = _vsnwprintf_s_wrapper(buffer, 6, _TRUNCATE, L"AB%uC", 123); + ok( ret == -1, "length wrong, expect=-1, got=%d\n", ret); + ok( !wcscmp(L"AB123", buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer)); - got = _vsnwprintf_s_wrapper(buffer, 2, _TRUNCATE, format, 123); - ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got); - ok( !wcscmp(out2, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer)); + ret = _vsnwprintf_s_wrapper(buffer, 2, _TRUNCATE, L"AB%uC", 123); + ok( ret == -1, "length wrong, expect=-1, got=%d\n", ret); + ok( !wcscmp(L"A", buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer)); - got = _vsnwprintf_s_wrapper(buffer, 1, _TRUNCATE, format, 123); - ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got); - ok( !wcscmp(out1, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer)); + ret = _vsnwprintf_s_wrapper(buffer, 1, _TRUNCATE, L"AB%uC", 123); + ok( ret == -1, "length wrong, expect=-1, got=%d\n", ret); + ok( !wcscmp(L"", buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer)); } static int WINAPIV _vsprintf_p_wrapper(char *str, size_t sizeOfBuffer, const char *format, ...) { int ret; - __ms_va_list valist; - __ms_va_start(valist, format); + va_list valist; + va_start(valist, format); ret = p__vsprintf_p(str, sizeOfBuffer, format, valist); - __ms_va_end(valist); + va_end(valist); return ret; } diff --git a/modules/rostests/winetests/msvcrt/scanf.c b/modules/rostests/winetests/msvcrt/scanf.c index 6d38e438c8c..e175342796b 100644 --- a/modules/rostests/winetests/msvcrt/scanf.c +++ b/modules/rostests/winetests/msvcrt/scanf.c @@ -22,6 +22,41 @@ #include "wine/test.h" +static void test_fscanf( void ) +{ + static const char file_name[] = "fscanf.tst"; + static const char contents[] = + "line1\n" + "line2 " + ; + char buf[1024]; + FILE *fp; + int ret; + + fp = fopen(file_name, "wb"); + ok(fp != NULL, "fp = %p\n", fp); + if(!fp) { + skip("failed to create temporary test file\n"); + return; + } + + ret = fprintf(fp, contents); + fclose(fp); + + fp = fopen(file_name, "rb"); + ret = fscanf(fp, "%s", buf); + ok(ret == 1, "ret = %d\n", ret); + ok(strcmp(buf, "line1") == 0, "buf = %s\n", buf); + ret = fscanf(fp, "%s", buf); + ok(ret == 1, "ret = %d\n", ret); + ok(strcmp(buf, "line2") == 0, "buf = %s\n", buf); + ret = fscanf(fp, "%s", buf); + ok(ret == EOF, "ret = %d\n", ret); + fclose(fp); + + unlink(file_name); +} + static void test_sscanf( void ) { /* use function pointers to bypass gcc builtin */ @@ -48,6 +83,14 @@ static void test_sscanf( void ) ret = p_sscanf(buffer, "%d", &result); ok( ret == EOF,"sscanf returns %x instead of %x\n", ret, EOF ); + ret = p_sscanf(" \t\n\n", "%s", buffer); + ok( ret == EOF, "ret = %d\n", ret ); + + buffer1[0] = 'a'; + ret = p_sscanf("test\n", "%s%c", buffer, buffer1); + ok( ret == 2, "ret = %d\n", ret ); + ok( buffer1[0] == '\n', "buffer1[0] = %d\n", buffer1[0] ); + /* check %p */ ok( p_sscanf("000000000046F170", "%p", &ptr) == 1, "sscanf failed\n" ); ok( ptr == (void *)0x46F170,"sscanf reads %p instead of %x\n", ptr, 0x46F170 ); @@ -122,6 +165,12 @@ static void test_sscanf( void ) ok(double_res >= 1.1e-30-1e-45 && double_res <= 1.1e-30+1e-45, "Got %.18le, expected %.18le\n", double_res, 1.1e-30); + buffer[0] = 0; + double_res = 1; + ret = p_sscanf(buffer, "%lf", &double_res); + ok(ret == -1, "expected 0, got %u\n", ret); + ok(double_res == 1, "Got %lf, expected 1\n", double_res); + /* check strings */ ret = p_sprintf(buffer," %s", pname); ok( ret == 26, "expected 26, got %u\n", ret); @@ -137,6 +186,22 @@ static void test_sscanf( void ) ok( ret == 1, "Error with format \"%s\"\n","%*[a-cd-dg-e]%c"); ok( buffer[0] == 'h', "Error with \"abcefgdh\" \"%c\"\n", buffer[0]); + ret = p_sscanf("-123", "%[-0-9]", buffer); + ok( ret == 1, "Error with format \"%s\"\n", "%[-0-9]"); + ok( strcmp("-123", buffer) == 0, "Error with \"-123\" \"%s\"\n", buffer); + + ret = p_sscanf("-321", "%[0-9-]", buffer); + ok( ret == 1, "Error with format \"%s\"\n", "%[0-9-]"); + ok( strcmp("-321", buffer) == 0, "Error with \"-321\" \"%s\"\n", buffer); + + ret = p_sscanf("-4123", "%[1-2-4]", buffer); + ok( ret == 1, "Error with format \"%s\"\n", "%[1-2-4]"); + ok( strcmp("-412", buffer) == 0, "Error with \"-412\" \"%s\"\n", buffer); + + ret = p_sscanf("-456123", "%[1-2-45-6]", buffer); + ok( ret == 1, "Error with format \"%s\"\n", "%[1-2-45-6]"); + ok( strcmp("-45612", buffer) == 0, "Error with \"-45612\" \"%s\"\n", buffer); + buffer1[0] = 'b'; ret = p_sscanf("a","%s%s", buffer, buffer1); ok( ret == 1, "expected 1, got %u\n", ret); @@ -162,6 +227,30 @@ static void test_sscanf( void ) ok(ret == 1, "Wrong number of arguments read: %d\n", ret); ok(result == 0xdead614e, "Wrong number read (%x)\n", result); + result = 0xdeadbeef; + strcpy(buffer,"12345678"); + ret = p_sscanf(buffer, "%02hd", &result); + ok(ret == 1, "Wrong number of arguments read: %d\n", ret); + ok(result == 0xdead000c, "Wrong number read (%x)\n", result); + + result = 0xdeadbeef; + strcpy(buffer,"12345678"); + ret = p_sscanf(buffer, "%h02d", &result); + ok(ret == 1, "Wrong number of arguments read: %d\n", ret); + ok(result == 0xdead000c, "Wrong number read (%x)\n", result); + + result = 0xdeadbeef; + strcpy(buffer,"12345678"); + ret = p_sscanf(buffer, "%000h02d", &result); + ok(ret == 1, "Wrong number of arguments read: %d\n", ret); + ok(result == 0xdead000c, "Wrong number read (%x)\n", result); + + result = 0xdeadbeef; + strcpy(buffer,"12345678"); + ret = p_sscanf(buffer, "%2h0d", &result); + ok(ret == 1, "Wrong number of arguments read: %d\n", ret); + ok(result == 0xdead614e, "Wrong number read (%x)\n", result); + result = 0xdeadbeef; ret = p_sscanf(buffer, "%hhd", &result); ok(ret == 1, "Wrong number of arguments read: %d\n", ret); @@ -313,35 +402,34 @@ static void test_sscanf_s(void) static void test_swscanf( void ) { - wchar_t buffer[100]; + wchar_t buffer[100], results[100]; int result, ret; - static const WCHAR formatd[] = {'%','d',0}; - const WCHAR format2[] = {'a',0x1234,'%',0x1234,'%','c',0}; WCHAR c; /* check WEOF */ /* WEOF is an unsigned short -1 but swscanf returns int so it should be sign-extended */ buffer[0] = 0; - ret = swscanf(buffer, formatd, &result); + ret = swscanf(buffer, L"%d", &result); /* msvcrt returns 0 but should return -1 (later versions do) */ ok( ret == (short)WEOF || broken(ret == 0), "swscanf returns %x instead of %x\n", ret, WEOF ); + ret = swscanf(L" \t\n\n", L"%s", results); + /* sscanf returns EOF under this case, but swscanf does not return WEOF */ + ok( ret == 0, "ret = %d\n", ret ); + buffer[0] = 'a'; buffer[1] = 0x1234; buffer[2] = 0x1234; buffer[3] = 'b'; - ret = swscanf(buffer, format2, &c); + ret = swscanf(buffer, L"a\x1234%\x1234%c", &c); ok(ret == 1, "swscanf returned %d\n", ret); ok(c == 'b', "c = %x\n", c); } static void test_swscanf_s(void) { - static const wchar_t fmt1[] = {'%','c',0}; - static const wchar_t fmt2[] = {'%','[','a','-','z',']',0}; - int (WINAPIV *pswscanf_s)(const wchar_t*,const wchar_t*,...); HMODULE hmod = GetModuleHandleA("msvcrt.dll"); wchar_t buf[2], out[2]; @@ -356,15 +444,15 @@ static void test_swscanf_s(void) buf[0] = 'a'; buf[1] = '1'; out[1] = 'b'; - ret = pswscanf_s(buf, fmt1, out, 1); + ret = pswscanf_s(buf, L"%c", out, 1); ok(ret == 1, "swscanf_s returned %d\n", ret); ok(out[0] == 'a', "out[0] = %x\n", out[0]); ok(out[1] == 'b', "out[1] = %x\n", out[1]); - ret = pswscanf_s(buf, fmt2, out, 1); + ret = pswscanf_s(buf, L"%[a-z]", out, 1); ok(!ret, "swscanf_s returned %d\n", ret); - ret = pswscanf_s(buf, fmt2, out, 2); + ret = pswscanf_s(buf, L"%[a-z]", out, 2); ... 2945 lines suppressed ...
2 weeks, 5 days
1
0
0
0
[reactos] 04/08: [CRT] math.h: fix definition of NAN
by Timo Kreuzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=736fea6c44cad243fcb8f…
commit 736fea6c44cad243fcb8f19b70acc803b5e20b30 Author: Timo Kreuzer <timo.kreuzer(a)reactos.org> AuthorDate: Thu Jan 30 19:27:53 2025 +0200 Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org> CommitDate: Wed Feb 12 16:54:45 2025 +0200 [CRT] math.h: fix definition of NAN - Use positive NAN by default - add support for _UCRT_NEGATIVE_NAN to legacy CRT headers - Use __builtin_nanf() on GCC/Clang --- sdk/include/crt/math.h | 16 +++++++++++++++- sdk/include/ucrt/corecrt_math.h | 8 ++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/sdk/include/crt/math.h b/sdk/include/crt/math.h index 33f460db5f6..09113acef86 100644 --- a/sdk/include/crt/math.h +++ b/sdk/include/crt/math.h @@ -57,7 +57,21 @@ typedef double double_t; #define HUGE_VALD ((double)INFINITY) #define HUGE_VALF ((float)INFINITY) #define HUGE_VALL ((long double)INFINITY) -#define NAN ((float)(INFINITY * 0.0F)) +#ifndef _UCRT_NEGATIVE_NAN +// This operation creates a negative NAN adding a - to make it positive +#ifdef _MSC_VER +#define NAN (-(float)(INFINITY * 0.0F)) +#else +#define NAN (__builtin_nanf("")) +#endif +#else +// Keep this for backwards compatibility +#ifdef _MSC_VER +#define NAN ((float)(INFINITY * 0.0F)) +#else +#define NAN (-__builtin_nanf("")) +#endif +#endif #define _DENORM (-2) #define _FINITE (-1) diff --git a/sdk/include/ucrt/corecrt_math.h b/sdk/include/ucrt/corecrt_math.h index fdfe1f02e66..215a0b96422 100644 --- a/sdk/include/ucrt/corecrt_math.h +++ b/sdk/include/ucrt/corecrt_math.h @@ -91,10 +91,18 @@ _CRT_BEGIN_C_HEADER #define HUGE_VALL ((long double)INFINITY) #ifndef _UCRT_NEGATIVE_NAN // This operation creates a negative NAN adding a - to make it positive +#ifdef _MSC_VER #define NAN (-(float)(INFINITY * 0.0F)) #else +#define NAN (__builtin_nanf("")) +#endif +#else // Keep this for backwards compatibility +#ifdef _MSC_VER #define NAN ((float)(INFINITY * 0.0F)) +#else +#define NAN (-__builtin_nanf("")) +#endif #endif #define _DENORM (-2)
2 weeks, 5 days
1
0
0
0
[reactos] 03/08: [WINE] test.h: Add wait_child_process
by Timo Kreuzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2fca81eca8bb2a95efa72…
commit 2fca81eca8bb2a95efa7286619f442acd641ba8f Author: Timo Kreuzer <timo.kreuzer(a)reactos.org> AuthorDate: Sat Oct 26 16:46:37 2024 +0300 Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org> CommitDate: Wed Feb 12 16:54:45 2025 +0200 [WINE] test.h: Add wait_child_process --- sdk/include/reactos/wine/test.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdk/include/reactos/wine/test.h b/sdk/include/reactos/wine/test.h index 4399a6f1714..35c2214e354 100644 --- a/sdk/include/reactos/wine/test.h +++ b/sdk/include/reactos/wine/test.h @@ -156,12 +156,14 @@ extern void winetest_pop_context(void); #define skip_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_skip #define win_skip_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_win_skip #define trace_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_trace +#define wait_child_process_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_wait_child_process #define subtest subtest_(__FILE__, __LINE__) #define ok ok_(__FILE__, __LINE__) #define skip skip_(__FILE__, __LINE__) #define win_skip win_skip_(__FILE__, __LINE__) #define trace trace_(__FILE__, __LINE__) +#define wait_child_process wait_child_process_(__FILE__, __LINE__) #define todo_if(is_todo) for (winetest_start_todo(is_todo); \ winetest_loop_todo(); \
2 weeks, 5 days
1
0
0
0
[reactos] 02/08: [MSVCRT] Export _get_heap_handle
by Timo Kreuzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c150c0a4560f7cbd2ea23…
commit c150c0a4560f7cbd2ea2395dde1c96e2da47c841 Author: Timo Kreuzer <timo.kreuzer(a)reactos.org> AuthorDate: Thu Jan 30 12:15:15 2025 +0200 Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org> CommitDate: Wed Feb 12 16:54:45 2025 +0200 [MSVCRT] Export _get_heap_handle --- dll/win32/msvcrt/msvcrt.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dll/win32/msvcrt/msvcrt.spec b/dll/win32/msvcrt/msvcrt.spec index f2f12e95c10..f0ec4ea34a5 100644 --- a/dll/win32/msvcrt/msvcrt.spec +++ b/dll/win32/msvcrt/msvcrt.spec @@ -555,7 +555,7 @@ @ cdecl -version=0x600+ _get_errno(ptr) @ stub -version=0x600+ _get_fileinfo @ stub -version=0x600+ _get_fmode -# @ cdecl _get_heap_handle() +@ cdecl _get_heap_handle() @ cdecl _get_osfhandle(long) @ cdecl -version=0x600+ _get_osplatform(ptr) @ stub -version=0x600+ _get_osver
2 weeks, 5 days
1
0
0
0
[reactos] 01/08: [NDK] Add FILE_MODE_INFORMATION
by Timo Kreuzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=05dfc83df5a89c9c53557…
commit 05dfc83df5a89c9c53557885886d7615134b1dd5 Author: Timo Kreuzer <timo.kreuzer(a)reactos.org> AuthorDate: Thu Jan 30 12:14:50 2025 +0200 Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org> CommitDate: Wed Feb 12 16:54:45 2025 +0200 [NDK] Add FILE_MODE_INFORMATION --- sdk/include/ndk/iotypes.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sdk/include/ndk/iotypes.h b/sdk/include/ndk/iotypes.h index 3e78ef20979..8ab6c146d18 100644 --- a/sdk/include/ndk/iotypes.h +++ b/sdk/include/ndk/iotypes.h @@ -892,6 +892,11 @@ typedef struct _FILE_PIPE_PEEK_BUFFER CHAR Data[1]; } FILE_PIPE_PEEK_BUFFER, *PFILE_PIPE_PEEK_BUFFER; +typedef struct _FILE_MODE_INFORMATION +{ + ULONG Mode; +} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION; + // // I/O Error Log Structures //
2 weeks, 5 days
1
0
0
0
← Newer
1
2
3
4
5
6
7
8
Older →
Jump to page:
1
2
3
4
5
6
7
8
Results per page:
10
25
50
100
200