Compare commits

...

33 Commits

Author SHA1 Message Date
Mahmoud Ahmed b88bd4f292
Merge 8bf0f03a3d into dcf9eb060a 2024-04-26 17:56:38 -07:00
Marcin Jabłoński dcf9eb060a
[SHELL32] Fix Control_RunDLLW (#5400)
This commit makes Control_RunDLLW pass all but one tests from rostests (the one test that fails is the first one, but it only fails if the path to the test program contains a space).

- Rework string parsing in the Control_DoLaunch routine
- Do not send the CPL_STARTWPARMSW message, if no extra parameters were specified (fixes the failing Got NULL lParam2! and some CPL_STARTWPARMSW: expected -1 got %d tests)
- Do not resolve invalid dialog names to index zero, unless the name is empty (fixes some of the failing CPL_DBLCLK: expected -1 got %d tests)
- Handle quotes in the second part of wszCmd

CORE-8981
2024-04-26 18:28:46 -06:00
Timo Kreuzer 45aa8f8111 [CRT] Remove useless #undef abort from process.h 2024-04-26 15:16:31 +02:00
Timo Kreuzer 6beff505d7 [CRT] Add _Exit to process.h
This is already done this way in our stdlib.h. It is needed by GCC 13 C++ headers. The problem happens like this:
- telnet/precomp.h includes fstream from GCC
- fstream includes pthread.h from GCC
- pthread.h includes process.h from ReactOS
- process.h defines _CRT_TERMINATE_DEFINED, but doesn't declare _Exit
- fstream includes cstdlib from GCC
- cstdlib includes stdlib.h from GCC (#include_next)
- stdlib.h doesn't declare _Exit, because _CRT_TERMINATE_DEFINED is defined
- cstdlib uses _Exit
2024-04-26 15:16:31 +02:00
Thamatip Chitpong cd0bb1af07 [TASKMGR] Process page: Allow using "Open File Location" functionality without running Explorer shell
If Explorer shell is not available, use ReactOS's alternative file browser instead.
2024-04-26 07:16:00 +07:00
Thamatip Chitpong 6d16d27462 [TASKMGR] Process page: Improve readability of command line string formatting code 2024-04-26 07:16:00 +07:00
Thamatip Chitpong 018264f38f
[NTUSER] Release modifier keys when deactivating message queue (#6754)
CORE-14768
2024-04-26 07:12:02 +07:00
Katayama Hirofumi MZ 1331e2fb02
[KERNEL32_APITEST] Add LCMapString testcase (#6805)
@tkreuzer said he wants LCMapString testcase in chat.
JIRA issue: N/A
2024-04-26 08:39:45 +09:00
Doug Lyons 3693d55404
[SHELL32] Fix Desktop folder details view (#5743)
* [SHELL32] Fix Desktop Folder Details View

JIRA issue: [CORE-19177|https://jira.reactos.org/browse/CORE-19177]

* Remove Comments column from Desktop Folder Details View and simplify code.
* Revise date/time sort based on reviewer comments.
* Swap size and type column positions for desktop folder details view.

With help from Whindmar, most (hopefully all) of the magic number for the columns
have been removed in all of the shell folders.

Co-authored-by: Whindmar Saksit <whindsaks@proton.me>
Co-authored-by: Carl J. Bialorucki <cbialo2@outlook.com>
2024-04-25 17:20:28 -05:00
Timo Kreuzer 1f49173f82 [CRT] Massively improve performance of rand_s
Cache the pointer to RtlGenRandom instead of loading and unloading advapi32 every single time this function is called.
2024-04-25 05:25:12 +02:00
Timo Kreuzer 3c55252828 [CRT_APITEST] Add test for rand_s 2024-04-25 05:25:12 +02:00
Timo Kreuzer f319538d98 [CRT] Move rand_s into it's own file 2024-04-25 05:25:12 +02:00
Timo Kreuzer 0ea48e79fc [CRT] Move _invalid_parameter into its own file
As the author of the code, I changed to license to MIT.
2024-04-25 05:25:12 +02:00
Timo Kreuzer 43beb913da [CRT] Move rand to stdlib, where it belongs 2024-04-25 05:25:12 +02:00
Katayama Hirofumi MZ d55f49978d
Revert "[SHELL32] SHChangeNotify: Use tree for CDirectoryList (#6784)" (#6800)
Reverts #6784 that was a guilty commit of CORE-19531 that causing performance regression.

JIRA issue: CORE-19531
2024-04-25 09:01:21 +09:00
Katayama Hirofumi MZ 91acf823d8
[SHELL32] SHChangeNotify: Use tree for CDirectoryList (#6784)
Optimize for speed and memory.
JIRA issue: CORE-13950
CDirectoryList class exists just for remembering which file item is a directory or
not, in order to notify the filesystem item changes. This information can
become a tree data structure.

- Add CFSPathIterator and CFSNode helper classes.
- CFSNode is a class for tree nodes.
- Re-implement CDirectoryList class by using tree nodes.
- Delete CDirectoryItem class.
2024-04-24 19:44:30 +09:00
Katayama Hirofumi MZ c0c270e90e [SHELL32_APITEST] Delete obsolete "iexplore.exe" tests
Follow-up to 75cc5b2. CORE-13950
2024-04-24 19:06:48 +09:00
Katayama Hirofumi MZ 75cc5b2b1c [SHELL32_APITEST] Commonize FindSubProgram function
and delete obsolete "iexplore.exe" tests. CORE-13950
2024-04-24 19:03:10 +09:00
Katayama Hirofumi MZ 8337df2bd1
[SHELL32_APITEST] SHChangeNotify: Improve coverity (#6798)
Improve coverity and speed.
JIRA issue: CORE-13950
- Move NUM_STAGE to the header file.
- Add stages.
- Add DIRTYPE_DESKTOP_DIR and
  DIRTYPE_PRINTERS directory types.
- Improve speed more.
2024-04-24 18:25:15 +09:00
Oleg Dubinskiy 24e088daa8
[MMEBUDDY] Implement support for looped wave playback (#6761)
Fix playing wave header multiple times in case the caller requests to do it.
In Windows, it is supported by WHDR_BEGINLOOP and WHDR_ENDLOOP flags (specified together) and dwLoops member of WAVEHDR structure (ususally set to 0xFFFFFFFF (INFINITE constant)).
- Check whenther WHDR_BEGINLOOP | WHDR_ENDLOOP flags are set by the caller.
- If they are, get the amount of times to play the header from WAVEHDR.dwLoops.
- Perform wave header competion only when the loop count is equal to zero. Otherwise, don't do it.
- When the header is entirely committed, in case completion is not needed, reset committed bytes count to the starting value to allow the header play again.
- Decrement loop count in case it isn't set to INFINITE, to mark loop as played correctly. When this count becomes zero, then the playback is finished.
- Get rid from SOUND_OVERLAPPED.PerformCompletion member. Use SOUND_DEVICE_INSTANCE.LoopsRemaining == 0 condition instead.
- Do this only for WaveOut devices, since MSDN states it works only with output buffers. Hence, there is nothing changed for WaveIn.
- Update an appropriate statement about unimplemented functionality from mmebuddy notes.
TODO: handle the case when multiple headers are requested to be looped (WHDR_BEGINLOOP and WHDR_ENDLOOP are set separatedly: 1st flag - in the 1st header, and 2nd in the last header). Currently, only looping a single wave header is supported.
This fixes the playback in the apps those request looped wave playback of some audio data (e. g., BRD Demo app, which did play its sound only first 500 ms before, now it plays endlessly until closing it manually).
CORE-10118
2024-04-24 11:08:40 +02:00
TabbyDev 8bf0f03a3d
[WINEMINE] Adding email to ar-SA 2024-03-24 02:14:43 +02:00
TabbyDev 00f360fc84
[WINEMINE] Adding email to ar-EG 2024-03-24 02:13:41 +02:00
Stanislav Motylkov 04806f528c
Update base/applications/games/winmine/lang/ar-SA.rc 2024-03-24 02:53:51 +03:00
Stanislav Motylkov 5579d260a4
Apply suggestions from code review 2024-03-24 02:52:30 +03:00
TabbyDev 89ddff351b
[WINEMINE] Add ar-EG to rsrc.rc 2024-03-23 21:17:19 +02:00
TabbyDev f9a1f8a5ac
[WINEMINE] Adding Egyptian Arabic 2024-03-23 21:15:57 +02:00
TabbyDev 195d82c1c0
[WINEMINE] Rename ar-AR.rc to ar-SA.rc 2024-03-23 20:52:12 +02:00
TabbyDev 81ddcfca71
[WINEMINE] Update base/applications/games/winmine/lang/ar-AR.rc
Co-authored-by: Stanislav Motylkov <x86corez@gmail.com>
2024-03-23 20:51:39 +02:00
TabbyDev de676b5288
[WINEMINE] Fix Iso lang in rsrc.rc for arabic 2024-03-23 20:50:52 +02:00
TabbyDev 3906df5562
Merge branch 'reactos:master' into master 2024-03-23 20:32:55 +02:00
TabbyDev 7e6358ba78
[WINMINE] Update ar-AR.rc 2024-03-22 16:07:02 +02:00
TabbyDev ccdc53f41d
Update ar-AR.rc 2024-03-22 16:05:27 +02:00
TabbyDev 758606af0b [WINEMINE] Adding Arabic to Winemine 2024-03-22 15:59:55 +02:00
43 changed files with 990 additions and 367 deletions

View File

@ -0,0 +1,80 @@
/*
* PROJECT: ReactOS WineMine
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: Arabic (Egypt) resource file
* TRANSLATOR: Copyright 2024 Mahmoud Ahmed <tabs90600@gmail.com>
*/
LANGUAGE LANG_ARABIC, SUBLANG_ARABIC_EGYPT
STRINGTABLE
BEGIN
IDS_APPNAME "WineMine"
IDS_NOBODY "لا أحد"
IDS_ABOUT "Copyright 2000 Joshua Thielen"
END
IDM_WINEMINE MENU
BEGIN
POPUP "الخيارات"
BEGIN
MENUITEM "لعبة جديدة\tF2", IDM_NEW
MENUITEM SEPARATOR
MENUITEM "حط علامة على السؤال", IDM_MARKQ
MENUITEM SEPARATOR
MENUITEM "مبتدئ", IDM_BEGINNER
MENUITEM "متقدم", IDM_ADVANCED
MENUITEM "خبير", IDM_EXPERT
MENUITEM "اختياري...", IDM_CUSTOM
MENUITEM SEPARATOR
MENUITEM "أخرج\tAlt+X", IDM_EXIT
END
POPUP "معلومات"
BEGIN
MENUITEM "أسرع الأوقات...", IDM_TIMES
MENUITEM "حول", IDM_ABOUT
END
END
DLG_TIMES DIALOGEX 0, 0, 160, 80
STYLE DS_MODALFRAME | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_POPUP | DS_SHELLFONT
CAPTION "أسرع الأوقات"
FONT 8, "MS Shell Dlg"
BEGIN
GROUPBOX "أسرع الأوقات", -1, 10, 10, 140, 45
LTEXT "مبتدئ", -1, 20, 20, 40, 8
LTEXT "متقدم", -1, 20, 30, 40, 8
LTEXT "خبير", -1, 20, 40, 40, 8
LTEXT "999", IDC_TIME1, 70, 20, 15, 8
LTEXT "999", IDC_TIME2, 70, 30, 15, 8
LTEXT "999", IDC_TIME3, 70, 40, 15, 8
LTEXT "", IDC_NAME1, 90, 20, 55, 8
LTEXT "", IDC_NAME2, 90, 30, 55, 8
LTEXT "", IDC_NAME3, 90, 40, 55, 8
DEFPUSHBUTTON "اوكي", IDOK, 55, 60, 50, 15
END
DLG_CONGRATS DIALOGEX 0, 0, 160, 60
STYLE DS_MODALFRAME | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_POPUP | DS_SHELLFONT
CAPTION "مبروك!"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "أكتب أسمك", -1, 10, 10, 150, 10
EDITTEXT IDC_EDITNAME, 25, 20, 110, 12
DEFPUSHBUTTON "اوكي", IDOK, 60, 40, 40, 15
END
DLG_CUSTOM DIALOGEX 0, 0, 100, 100
STYLE DS_MODALFRAME | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_POPUP | DS_SHELLFONT
CAPTION "لعبه اختياريه"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "Rows", -1, 5, 5, 30, 10
LTEXT "Cols", -1, 5, 35, 30, 10
LTEXT "Mines", -1, 5, 65, 30, 10
EDITTEXT IDC_EDITROWS, 5, 15, 20, 12, ES_NUMBER
EDITTEXT IDC_EDITCOLS, 5, 45, 20, 12, ES_NUMBER
EDITTEXT IDC_EDITMINES, 5, 75, 20, 12, ES_NUMBER
DEFPUSHBUTTON "اوكي", IDOK, 40, 30, 50, 15
PUSHBUTTON "إلغاء", IDCANCEL, 40, 50, 50, 15
END

View File

@ -0,0 +1,80 @@
/*
* PROJECT: ReactOS WineMine
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: Arabic (Saudi Arabia) resource file
* TRANSLATOR: Copyright 2024 Mahmoud Ahmed <tabs90600@gmail.com>
*/
LANGUAGE LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA
STRINGTABLE
BEGIN
IDS_APPNAME "WineMine"
IDS_NOBODY "لا أحد"
IDS_ABOUT "Copyright 2000 Joshua Thielen"
END
IDM_WINEMINE MENU
BEGIN
POPUP "الخيارات"
BEGIN
MENUITEM "لعبة جديدة\tF2", IDM_NEW
MENUITEM SEPARATOR
MENUITEM "ضع علامة على السؤال", IDM_MARKQ
MENUITEM SEPARATOR
MENUITEM "مبتدئ", IDM_BEGINNER
MENUITEM "متقدم", IDM_ADVANCED
MENUITEM "خبير", IDM_EXPERT
MENUITEM "اختياري...", IDM_CUSTOM
MENUITEM SEPARATOR
MENUITEM "أخرج\tAlt+X", IDM_EXIT
END
POPUP "معلومات"
BEGIN
MENUITEM "أسرع الأوقات...", IDM_TIMES
MENUITEM "حول", IDM_ABOUT
END
END
DLG_TIMES DIALOGEX 0, 0, 160, 80
STYLE DS_MODALFRAME | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_POPUP | DS_SHELLFONT
CAPTION "أسرع الأوقات"
FONT 8, "MS Shell Dlg"
BEGIN
GROUPBOX "أسرع الأوقات", -1, 10, 10, 140, 45
LTEXT "مبتدئ", -1, 20, 20, 40, 8
LTEXT "متقدم", -1, 20, 30, 40, 8
LTEXT "خبير", -1, 20, 40, 40, 8
LTEXT "999", IDC_TIME1, 70, 20, 15, 8
LTEXT "999", IDC_TIME2, 70, 30, 15, 8
LTEXT "999", IDC_TIME3, 70, 40, 15, 8
LTEXT "", IDC_NAME1, 90, 20, 55, 8
LTEXT "", IDC_NAME2, 90, 30, 55, 8
LTEXT "", IDC_NAME3, 90, 40, 55, 8
DEFPUSHBUTTON "OK", IDOK, 55, 60, 50, 15
END
DLG_CONGRATS DIALOGEX 0, 0, 160, 60
STYLE DS_MODALFRAME | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_POPUP | DS_SHELLFONT
CAPTION "تهانينا!"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "أدخل أسمك", -1, 10, 10, 150, 10
EDITTEXT IDC_EDITNAME, 25, 20, 110, 12
DEFPUSHBUTTON "نعم", IDOK, 60, 40, 40, 15
END
DLG_CUSTOM DIALOGEX 0, 0, 100, 100
STYLE DS_MODALFRAME | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_POPUP | DS_SHELLFONT
CAPTION "لعبه اختياريه"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "Rows", -1, 5, 5, 30, 10
LTEXT "Cols", -1, 5, 35, 30, 10
LTEXT "Mines", -1, 5, 65, 30, 10
EDITTEXT IDC_EDITROWS, 5, 15, 20, 12, ES_NUMBER
EDITTEXT IDC_EDITCOLS, 5, 45, 20, 12, ES_NUMBER
EDITTEXT IDC_EDITMINES, 5, 75, 20, 12, ES_NUMBER
DEFPUSHBUTTON "نعم", IDOK, 40, 30, 50, 15
PUSHBUTTON "إلغاء", IDCANCEL, 40, 50, 50, 15
END

View File

@ -51,6 +51,12 @@ IDI_MINES BITMAP "rc/mines.bmp"
/* UTF-8 */
#pragma code_page(65001)
#ifdef LANGUAGE_AR_SA
#include "lang/ar-SA.rc"
#endif
#ifdef LANGUAGE_AR_EG
#include "lang/ar-EG.rc"
#endif
#ifdef LANGUAGE_BG_BG
#include "lang/bg-BG.rc"
#endif

View File

@ -1222,6 +1222,7 @@ void ProcessPage_OnOpenFileLocation(void)
DWORD dwProcessId;
DWORD dwLength;
LPWSTR pszExePath;
static const WCHAR szCmdFormat[] = L"/select,\"%s\"";
LPWSTR pszCmdLine = NULL;
dwProcessId = GetSelectedProcessId();
@ -1240,14 +1241,18 @@ void ProcessPage_OnOpenFileLocation(void)
goto Cleanup;
/* Build the shell command line */
pszCmdLine = HeapAlloc(GetProcessHeap(), 0, (dwLength + CONST_STR_LEN(L"/select,\"\"")) * sizeof(WCHAR));
dwLength += CONST_STR_LEN(szCmdFormat) - CONST_STR_LEN(L"%s");
pszCmdLine = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR));
if (!pszCmdLine)
goto Cleanup;
StringCchPrintfW(pszCmdLine, dwLength + CONST_STR_LEN(L"/select,\"\""), L"/select,\"%s\"", pszExePath);
StringCchPrintfW(pszCmdLine, dwLength, szCmdFormat, pszExePath);
/* Call the shell to open the file location and select it */
ShellExecuteW(NULL, L"open", L"explorer.exe", pszCmdLine, NULL, SW_SHOWNORMAL);
/* Call the shell to open the file location and select it. If Explorer shell
* is not available, use ReactOS's alternative file browser instead. */
ShellExecuteW(NULL, L"open",
GetShellWindow() ? L"explorer.exe" : L"filebrowser.exe",
pszCmdLine, NULL, SW_SHOWNORMAL);
Cleanup:
HeapFree(GetProcessHeap(), 0, pszCmdLine);

View File

@ -550,7 +550,7 @@ HRESULT WINAPI CControlPanelFolder::GetDefaultColumnState(UINT iColumn, DWORD *p
if (!pcsFlags || iColumn >= CONTROLPANEL_COL_COUNT)
return E_INVALIDARG;
*pcsFlags = ControlPanelSFHeader[iColumn].pcsFlags;
*pcsFlags = ControlPanelSFHeader[iColumn].colstate;
return S_OK;
}

View File

@ -21,6 +21,7 @@
*/
#include <precomp.h>
#include "CFSFolder.h" // Only for CFSFolder::*FSColumn* helpers!
WINE_DEFAULT_DEBUG_CHANNEL(shell);
@ -284,17 +285,6 @@ class CDesktopFolderEnum :
int SHELL_ConfirmMsgBox(HWND hWnd, LPWSTR lpszText, LPWSTR lpszCaption, HICON hIcon, BOOL bYesToAll);
static const shvheader DesktopSFHeader[] = {
{IDS_SHV_COLUMN_NAME, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 15},
{IDS_SHV_COLUMN_COMMENTS, SHCOLSTATE_TYPE_STR, LVCFMT_LEFT, 10},
{IDS_SHV_COLUMN_TYPE, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 10},
{IDS_SHV_COLUMN_SIZE, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
{IDS_SHV_COLUMN_MODIFIED, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 12},
{IDS_SHV_COLUMN_ATTRIBUTES, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 10}
};
#define DESKTOPSHELLVIEWCOLUMNS 6
static const DWORD dwDesktopAttributes =
SFGAO_HASSUBFOLDER | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR |
SFGAO_STORAGEANCESTOR | SFGAO_HASPROPSHEET | SFGAO_STORAGE;
@ -978,16 +968,25 @@ HRESULT WINAPI CDesktopFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG
return S_OK;
}
HRESULT WINAPI CDesktopFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
HRESULT WINAPI CDesktopFolder::GetDefaultColumnState(UINT iColumn, SHCOLSTATEF *pcsFlags)
{
HRESULT hr;
TRACE ("(%p)\n", this);
if (!pcsFlags || iColumn >= DESKTOPSHELLVIEWCOLUMNS)
if (!pcsFlags)
return E_INVALIDARG;
*pcsFlags = DesktopSFHeader[iColumn].pcsFlags;
return S_OK;
hr = CFSFolder::GetDefaultFSColumnState(iColumn, *pcsFlags);
/*
// CDesktopFolder may override the flags if desired (future)
switch(iColumn)
{
case SHFSF_COL_FATTS:
*pcsFlags &= ~SHCOLSTATE_ONBYDEFAULT;
break;
}
*/
return hr;
}
HRESULT WINAPI CDesktopFolder::GetDetailsEx(
@ -1000,19 +999,27 @@ HRESULT WINAPI CDesktopFolder::GetDetailsEx(
return E_NOTIMPL;
}
/*************************************************************************
* Column info functions.
* CFSFolder.h provides defaults for us.
*/
HRESULT CDesktopFolder::GetColumnDetails(UINT iColumn, SHELLDETAILS &sd)
{
/* CDesktopFolder may override the flags and/or name if desired */
return CFSFolder::GetFSColumnDetails(iColumn, sd);
}
HRESULT WINAPI CDesktopFolder::GetDetailsOf(
PCUITEMID_CHILD pidl,
UINT iColumn,
SHELLDETAILS *psd)
{
if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS)
if (!psd)
return E_INVALIDARG;
if (!pidl)
{
psd->fmt = DesktopSFHeader[iColumn].fmt;
psd->cxChar = DesktopSFHeader[iColumn].cxChar;
return SHSetStrRet(&psd->str, DesktopSFHeader[iColumn].colnameid);
return GetColumnDetails(iColumn, *psd);
}
CComPtr<IShellFolder2> psf;

View File

@ -42,6 +42,8 @@ class CDesktopFolder :
HRESULT _GetSFFromPidl(LPCITEMIDLIST pidl, IShellFolder2** psf);
static HRESULT GetColumnDetails(UINT iColumn, SHELLDETAILS &sd);
HRESULT _ParseDisplayNameByParent(
HWND hwndOwner,
LPBC pbc,

View File

@ -1168,13 +1168,13 @@ HRESULT WINAPI CDrivesFolder::GetDefaultColumn (DWORD dwRes, ULONG *pSort, ULONG
return S_OK;
}
HRESULT WINAPI CDrivesFolder::GetDefaultColumnState(UINT iColumn, DWORD * pcsFlags)
HRESULT WINAPI CDrivesFolder::GetDefaultColumnState(UINT iColumn, SHCOLSTATEF * pcsFlags)
{
TRACE("(%p)\n", this);
if (!pcsFlags || iColumn >= _countof(MyComputerSFHeader))
return E_INVALIDARG;
*pcsFlags = MyComputerSFHeader[iColumn].pcsFlags;
*pcsFlags = MyComputerSFHeader[iColumn].colstate;
return S_OK;
}

View File

@ -527,17 +527,35 @@ CFSFolder::~CFSFolder()
SHFree(m_sPathTarget);
}
static const shvheader GenericSFHeader[] = {
{IDS_SHV_COLUMN_NAME, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 15},
{IDS_SHV_COLUMN_SIZE, SHCOLSTATE_TYPE_INT | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
{IDS_SHV_COLUMN_TYPE, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 10},
{IDS_SHV_COLUMN_SIZE, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
{IDS_SHV_COLUMN_MODIFIED, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 12},
{IDS_SHV_COLUMN_MODIFIED, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 15},
{IDS_SHV_COLUMN_ATTRIBUTES, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 10},
{IDS_SHV_COLUMN_COMMENTS, SHCOLSTATE_TYPE_STR, LVCFMT_LEFT, 10}
{IDS_SHV_COLUMN_COMMENTS, SHCOLSTATE_TYPE_STR | SHCOLSTATE_SLOW, LVCFMT_LEFT, 10}, // We don't currently support comments but CRegFolder does
};
#define GENERICSHELLVIEWCOLUMNS 6
#define GENERICSHELLVIEWCOLUMNS _countof(GenericSFHeader)
HRESULT CFSFolder::GetFSColumnDetails(UINT iColumn, SHELLDETAILS &sd)
{
if (iColumn >= _countof(GenericSFHeader))
return E_INVALIDARG;
sd.fmt = GenericSFHeader[iColumn].fmt;
sd.cxChar = GenericSFHeader[iColumn].cxChar;
return SHSetStrRet(&sd.str, GenericSFHeader[iColumn].colnameid);
}
HRESULT CFSFolder::GetDefaultFSColumnState(UINT iColumn, SHCOLSTATEF &csFlags)
{
if (iColumn >= _countof(GenericSFHeader))
return E_INVALIDARG;
csFlags = GenericSFHeader[iColumn].colstate;
return S_OK;
}
static HRESULT SHELL32_GetCLSIDForDirectory(LPCWSTR pwszDir, LPCWSTR KeyName, CLSID* pclsidFolder)
{
@ -1021,18 +1039,13 @@ HRESULT WINAPI CFSFolder::CompareIDs(LPARAM lParam,
return MAKE_COMPARE_HRESULT(bIsFolder1 ? -1 : 1);
}
int result;
int result = 0;
switch (LOWORD(lParam))
{
case 0: /* Name */
case SHFSF_COL_NAME:
result = wcsicmp(pDataW1->wszName, pDataW2->wszName);
break;
case 1: /* Type */
pExtension1 = PathFindExtensionW(pDataW1->wszName);
pExtension2 = PathFindExtensionW(pDataW2->wszName);
result = wcsicmp(pExtension1, pExtension2);
break;
case 2: /* Size */
case SHFSF_COL_SIZE:
if (pData1->u.file.dwFileSize > pData2->u.file.dwFileSize)
result = 1;
else if (pData1->u.file.dwFileSize < pData2->u.file.dwFileSize)
@ -1040,16 +1053,26 @@ HRESULT WINAPI CFSFolder::CompareIDs(LPARAM lParam,
else
result = 0;
break;
case 3: /* Modified */
case SHFSF_COL_TYPE:
pExtension1 = PathFindExtensionW(pDataW1->wszName);
pExtension2 = PathFindExtensionW(pDataW2->wszName);
result = wcsicmp(pExtension1, pExtension2);
break;
case SHFSF_COL_MDATE:
result = pData1->u.file.uFileDate - pData2->u.file.uFileDate;
if (result == 0)
result = pData1->u.file.uFileTime - pData2->u.file.uFileTime;
break;
case 4: /* Attributes */
case SHFSF_COL_FATTS:
return SHELL32_CompareDetails(this, lParam, pidl1, pidl2);
case 5: /* Comments */
case SHFSF_COL_COMMENT:
result = 0;
break;
default:
if (_ILIsPidlSimple(pidl1) || _ILIsPidlSimple(pidl2))
ERR("Unknown column %u, can't compare\n", LOWORD(lParam));
else
TRACE("Unknown column %u, deferring to the subfolder\n", LOWORD(lParam));
}
if (result == 0)
@ -1543,16 +1566,14 @@ HRESULT WINAPI CFSFolder::GetDefaultColumn(DWORD dwRes,
}
HRESULT WINAPI CFSFolder::GetDefaultColumnState(UINT iColumn,
DWORD * pcsFlags)
SHCOLSTATEF *pcsFlags)
{
TRACE ("(%p)\n", this);
if (!pcsFlags || iColumn >= GENERICSHELLVIEWCOLUMNS)
if (!pcsFlags)
return E_INVALIDARG;
*pcsFlags = GenericSFHeader[iColumn].pcsFlags;
return S_OK;
else
return GetDefaultFSColumnState(iColumn, *pcsFlags);
}
HRESULT WINAPI CFSFolder::GetDetailsEx(PCUITEMID_CHILD pidl,
@ -1576,9 +1597,7 @@ HRESULT WINAPI CFSFolder::GetDetailsOf(PCUITEMID_CHILD pidl,
if (!pidl)
{
/* the header titles */
psd->fmt = GenericSFHeader[iColumn].fmt;
psd->cxChar = GenericSFHeader[iColumn].cxChar;
return SHSetStrRet(&psd->str, GenericSFHeader[iColumn].colnameid);
return GetFSColumnDetails(iColumn, *psd);
}
else
{
@ -1587,24 +1606,30 @@ HRESULT WINAPI CFSFolder::GetDetailsOf(PCUITEMID_CHILD pidl,
/* the data from the pidl */
switch (iColumn)
{
case 0: /* name */
case SHFSF_COL_NAME:
hr = GetDisplayNameOf (pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
break;
case 1: /* type */
_ILGetFileType(pidl, psd->str.cStr, MAX_PATH);
break;
case 2: /* size */
case SHFSF_COL_SIZE:
_ILGetFileSize(pidl, psd->str.cStr, MAX_PATH);
break;
case 3: /* date */
case SHFSF_COL_TYPE:
_ILGetFileType(pidl, psd->str.cStr, MAX_PATH);
break;
case SHFSF_COL_MDATE:
_ILGetFileDate(pidl, psd->str.cStr, MAX_PATH);
break;
case 4: /* attributes */
case SHFSF_COL_FATTS:
_ILGetFileAttributes(pidl, psd->str.cStr, MAX_PATH);
break;
case 5: /* FIXME: comments */
psd->str.cStr[0] = 0;
case SHFSF_COL_COMMENT:
psd->str.cStr[0] = '\0'; // TODO: Extract comment from .lnk files? desktop.ini?
break;
#if DBG
default:
ERR("Missing case for column %d\n", iColumn);
#else
DEFAULT_UNREACHABLE;
#endif
}
}

View File

@ -125,6 +125,11 @@ class CFSFolder :
protected:
HRESULT WINAPI GetCustomViewInfo(ULONG unknown, SFVM_CUSTOMVIEWINFO_DATA *data);
public:
// Helper functions shared with CDesktopFolder
static HRESULT GetFSColumnDetails(UINT iColumn, SHELLDETAILS &sd);
static HRESULT GetDefaultFSColumnState(UINT iColumn, SHCOLSTATEF &csFlags);
};
#endif /* _CFSFOLDER_H_ */

View File

@ -510,13 +510,13 @@ HRESULT WINAPI CNetFolder::GetDefaultColumn (DWORD dwRes, ULONG *pSort, ULONG *p
return S_OK;
}
HRESULT WINAPI CNetFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
HRESULT WINAPI CNetFolder::GetDefaultColumnState(UINT iColumn, SHCOLSTATEF *pcsFlags)
{
TRACE("(%p)\n", this);
if (!pcsFlags || iColumn >= NETWORKPLACESSHELLVIEWCOLUMNS)
return E_INVALIDARG;
*pcsFlags = NetworkPlacesSFHeader[iColumn].pcsFlags;
*pcsFlags = NetworkPlacesSFHeader[iColumn].colstate;
return S_OK;
}

View File

@ -432,11 +432,11 @@ HRESULT WINAPI CPrinterFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG
return S_OK;
}
HRESULT WINAPI CPrinterFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
HRESULT WINAPI CPrinterFolder::GetDefaultColumnState(UINT iColumn, SHCOLSTATEF *pcsFlags)
{
if (!pcsFlags || iColumn >= PrinterSHELLVIEWCOLUMNS)
return E_INVALIDARG;
*pcsFlags = PrinterSFHeader[iColumn].pcsFlags;
*pcsFlags = PrinterSFHeader[iColumn].colstate;
return S_OK;
}

View File

@ -233,14 +233,6 @@ class CRegFolderEnum :
END_COM_MAP()
};
enum registry_columns
{
REGISTRY_COL_NAME,
REGISTRY_COL_TYPE,
REGISTRY_COL_VALUE,
REGISTRY_COL_COUNT,
};
CRegFolderEnum::CRegFolderEnum()
{
}
@ -302,6 +294,18 @@ HRESULT CRegFolderEnum::AddItemsFromKey(HKEY hkey_root, LPCWSTR szRepPath)
return S_OK;
}
/*
* These columns try to map to CFSFolder's columns because the CDesktopFolder
* displays CFSFolder and CRegFolder items in the same view.
*/
enum REGFOLDERCOLUMNINDEX
{
COL_NAME = SHFSF_COL_NAME,
COL_TYPE = SHFSF_COL_TYPE,
COL_INFOTIP = SHFSF_COL_COMMENT,
REGFOLDERCOLUMNCOUNT = max(COL_INFOTIP, COL_TYPE) + 1
};
class CRegFolder :
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IShellFolder2
@ -808,7 +812,7 @@ HRESULT WINAPI CRegFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pD
HRESULT WINAPI CRegFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
{
if (iColumn >= REGISTRY_COL_COUNT)
if (iColumn >= REGFOLDERCOLUMNCOUNT)
return E_INVALIDARG;
*pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT;
return S_OK;
@ -824,6 +828,12 @@ HRESULT WINAPI CRegFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHEL
if (!psd)
return E_INVALIDARG;
if (!pidl)
{
TRACE("CRegFolder has no column info\n");
return E_INVALIDARG;
}
GUID const *clsid = _ILGetGUIDPointer (pidl);
if (!clsid)
@ -834,11 +844,11 @@ HRESULT WINAPI CRegFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHEL
switch(iColumn)
{
case REGISTRY_COL_NAME:
case COL_NAME:
return GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
case REGISTRY_COL_TYPE:
case COL_TYPE:
return SHSetStrRet(&psd->str, IDS_SYSTEMFOLDER);
case REGISTRY_COL_VALUE:
case COL_INFOTIP:
HKEY hKey;
if (!HCR_RegOpenClassIDKey(*clsid, &hKey))
return SHSetStrRet(&psd->str, "");

View File

@ -27,11 +27,25 @@
#define CHARS_IN_GUID 39
typedef struct {
int colnameid;
int pcsFlags;
int fmt;
int cxChar;
WORD colnameid; // Column title text resource id passed to LoadString
WORD colstate; // SHCOLSTATEF returned by IShellFolder2::GetDefaultColumnState
// HACK: SHCOLSTATEF truncated to WORD to reduce .rdata section size
WORD fmt; // LVCFMT_*
WORD cxChar; // Column width hint
} shvheader;
/*
* CFSFolder column indices. CDesktopFolder MUST use the same indices!
* According to the documentation for IShellFolder2::GetDetailsOf,
* the first 4 columns for SFGAO_FILESYSTEM items must be Name, Size, Type, Modified date
For Details See:
https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellfolder2-getdetailsof
*/
#define SHFSF_COL_NAME 0
#define SHFSF_COL_SIZE 1
#define SHFSF_COL_TYPE 2 // SHGFI_TYPENAME
#define SHFSF_COL_MDATE 3 // Modified date
#define SHFSF_COL_FATTS 4 // File attributes
#define SHFSF_COL_COMMENT 5
#define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00)
#define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)

View File

@ -873,6 +873,7 @@ static void Control_DoLaunch(CPanel* panel, HWND hWnd, LPCWSTR wszCmd)
* "a path\foo.cpl"
*/
{
#ifndef __REACTOS__
LPWSTR buffer;
LPWSTR beg = NULL;
LPWSTR end;
@ -952,14 +953,6 @@ static void Control_DoLaunch(CPanel* panel, HWND hWnd, LPCWSTR wszCmd)
applet = Control_LoadApplet(hWnd, buffer, panel);
if (applet)
{
#ifdef __REACTOS__
ULONG_PTR cookie;
BOOL bActivated;
ATOM aCPLName;
ATOM aCPLFlags;
ATOM aCPLPath;
AppDlgFindData findData;
#endif
/* we've been given a textual parameter (or none at all) */
if (sp == -1) {
while ((++sp) != applet->count) {
@ -975,65 +968,201 @@ static void Control_DoLaunch(CPanel* panel, HWND hWnd, LPCWSTR wszCmd)
sp = 0;
}
#ifdef __REACTOS__
bActivated = (applet->hActCtx != INVALID_HANDLE_VALUE ? ActivateActCtx(applet->hActCtx, &cookie) : FALSE);
aCPLPath = GlobalFindAtomW(applet->cmd);
if (!aCPLPath)
{
aCPLPath = GlobalAddAtomW(applet->cmd);
}
aCPLName = GlobalFindAtomW(L"CPLName");
if (!aCPLName)
{
aCPLName = GlobalAddAtomW(L"CPLName");
}
aCPLFlags = GlobalFindAtomW(L"CPLFlags");
if (!aCPLFlags)
{
aCPLFlags = GlobalAddAtomW(L"CPLFlags");
}
findData.szAppFile = applet->cmd;
findData.sAppletNo = (UINT_PTR)(sp + 1);
findData.aCPLName = aCPLName;
findData.aCPLFlags = aCPLFlags;
findData.hRunDLL = applet->hWnd;
findData.hDlgResult = NULL;
// Find the dialog of this applet in the first instance.
// Note: The simpler functions "FindWindow" or "FindWindowEx" does not find this type of dialogs.
EnumWindows(Control_EnumWinProc, (LPARAM)&findData);
if (findData.hDlgResult)
{
BringWindowToTop(findData.hDlgResult);
}
else
{
SetPropW(applet->hWnd, (LPTSTR)MAKEINTATOM(aCPLName), (HANDLE)MAKEINTATOM(aCPLPath));
SetPropW(applet->hWnd, (LPTSTR)MAKEINTATOM(aCPLFlags), UlongToHandle(sp + 1));
Control_ShowAppletInTaskbar(applet, sp);
#endif
if (!applet->proc(applet->hWnd, CPL_STARTWPARMSW, sp, (LPARAM)extraPmts))
applet->proc(applet->hWnd, CPL_DBLCLK, sp, applet->info[sp].data);
#ifdef __REACTOS__
RemovePropW(applet->hWnd, applet->cmd);
GlobalDeleteAtom(aCPLPath);
}
#endif
Control_UnloadApplet(applet);
#ifdef __REACTOS__
if (bActivated)
DeactivateActCtx(0, cookie);
#endif
}
HeapFree(GetProcessHeap(), 0, buffer);
#else
LPWSTR buffer;
LPWSTR ptr;
signed sp = -1;
LPCWSTR extraPmts = L"";
BOOL quoted = FALSE;
CPlApplet *applet;
LPCWSTR pchFirstComma = NULL, pchSecondComma = NULL;
LPCWSTR pchLastUnquotedSpace = NULL;
LPWSTR wszDialogBoxName;
int i = 0;
SIZE_T nLen = lstrlenW(wszCmd);
buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*buffer) * (nLen + 1));
wszDialogBoxName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wszDialogBoxName) * (nLen + 1));
if (wszDialogBoxName == NULL || buffer == NULL)
{
if (buffer != NULL)
HeapFree(GetProcessHeap(), 0, buffer);
if (wszDialogBoxName != NULL)
HeapFree(GetProcessHeap(), 0, wszDialogBoxName);
return;
}
/* Search for unquoted commas and spaces. */
for (i = 0; i < nLen; i++)
{
if (quoted && wszCmd[i] != L'"')
continue;
switch (wszCmd[i])
{
case L'"':
quoted = !quoted;
break;
case L',':
if (!pchFirstComma)
pchFirstComma = &wszCmd[i];
else if (!pchSecondComma)
pchSecondComma = &wszCmd[i];
break;
case L' ':
pchLastUnquotedSpace = &wszCmd[i];
break;
}
}
/* If no unquoted commas are found, parameters are either space separated, or the entire string
* is a CPL path. */
if (!pchFirstComma)
{
/* An unquoted space was found in the string. Assume the last word is the dialog box
* name/number. */
if (pchLastUnquotedSpace)
{
int nSpaces = 0;
while (pchLastUnquotedSpace[nSpaces] == L' ')
nSpaces++;
StringCchCopyNW(buffer, nLen + 1, wszCmd, pchLastUnquotedSpace - wszCmd);
StringCchCopyW(wszDialogBoxName, nLen + 1, pchLastUnquotedSpace + nSpaces);
}
/* No parameters were passed, the entire string is the CPL path. */
else
{
StringCchCopyW(buffer, nLen + 1, wszCmd);
}
}
/* If an unquoted comma was found, there are at least two parts of the string:
* - the CPL path
* - either a dialog box number preceeded by @, or a dialog box name.
* If there was a second unqoted comma, there is another part of the string:
* - the rest of the parameters. */
else
{
/* If there was no second unquoted comma in the string, the CPL path ends at thes
* null terminator. */
if (!pchSecondComma)
pchSecondComma = wszCmd + nLen;
StringCchCopyNW(buffer, nLen + 1, wszCmd, pchFirstComma - wszCmd);
StringCchCopyNW(wszDialogBoxName,
nLen + 1,
pchFirstComma + 1,
pchSecondComma - pchFirstComma - 1);
if (pchSecondComma != wszCmd + nLen)
{
extraPmts = pchSecondComma + 1;
}
}
/* Remove the quotes from both buffers. */
while ((ptr = StrChrW(buffer, '"')))
memmove(ptr, ptr+1, lstrlenW(ptr)*sizeof(WCHAR));
while ((ptr = StrChrW(wszDialogBoxName, '"')))
memmove(ptr, ptr+1, lstrlenW(ptr)*sizeof(WCHAR));
if (wszDialogBoxName[0] == L'@')
{
sp = _wtoi(wszDialogBoxName + 1);
}
TRACE("cmd %s, extra %s, sp %d\n", debugstr_w(buffer), debugstr_w(extraPmts), sp);
applet = Control_LoadApplet(hWnd, buffer, panel);
if (applet)
{
ULONG_PTR cookie;
BOOL bActivated;
ATOM aCPLName;
ATOM aCPLFlags;
ATOM aCPLPath;
AppDlgFindData findData;
/* we've been given a textual parameter (or none at all) */
if (sp == -1)
{
while ((++sp) != applet->count)
{
TRACE("sp %d, name %s\n", sp, debugstr_w(applet->info[sp].name));
if (StrCmpIW(wszDialogBoxName, applet->info[sp].name) == 0)
break;
}
}
if (sp >= applet->count && wszDialogBoxName[0] == L'\0')
{
sp = 0;
}
bActivated = (applet->hActCtx != INVALID_HANDLE_VALUE ? ActivateActCtx(applet->hActCtx, &cookie) : FALSE);
if (sp < applet->count)
{
aCPLPath = GlobalFindAtomW(applet->cmd);
if (!aCPLPath)
aCPLPath = GlobalAddAtomW(applet->cmd);
aCPLName = GlobalFindAtomW(L"CPLName");
if (!aCPLName)
aCPLName = GlobalAddAtomW(L"CPLName");
aCPLFlags = GlobalFindAtomW(L"CPLFlags");
if (!aCPLFlags)
aCPLFlags = GlobalAddAtomW(L"CPLFlags");
findData.szAppFile = applet->cmd;
findData.sAppletNo = (UINT_PTR)(sp + 1);
findData.aCPLName = aCPLName;
findData.aCPLFlags = aCPLFlags;
findData.hRunDLL = applet->hWnd;
findData.hDlgResult = NULL;
// Find the dialog of this applet in the first instance.
// Note: The simpler functions "FindWindow" or "FindWindowEx" does not find this type of dialogs.
EnumWindows(Control_EnumWinProc, (LPARAM)&findData);
if (findData.hDlgResult)
{
BringWindowToTop(findData.hDlgResult);
}
else
{
SetPropW(applet->hWnd, (LPTSTR)MAKEINTATOM(aCPLName), (HANDLE)MAKEINTATOM(aCPLPath));
SetPropW(applet->hWnd, (LPTSTR)MAKEINTATOM(aCPLFlags), UlongToHandle(sp + 1));
Control_ShowAppletInTaskbar(applet, sp);
if (extraPmts[0] == L'\0' ||
!applet->proc(applet->hWnd, CPL_STARTWPARMSW, sp, (LPARAM)extraPmts))
{
applet->proc(applet->hWnd, CPL_DBLCLK, sp, applet->info[sp].data);
}
RemovePropW(applet->hWnd, applet->cmd);
GlobalDeleteAtom(aCPLPath);
}
}
Control_UnloadApplet(applet);
if (bActivated)
DeactivateActCtx(0, cookie);
}
HeapFree(GetProcessHeap(), 0, buffer);
HeapFree(GetProcessHeap(), 0, wszDialogBoxName);
#endif
}
/*************************************************************************

View File

@ -2467,7 +2467,7 @@ FinishDlgProc(HWND hwndDlg,
if (!SetupData->UnattendSetup || !SetupData->DisableGeckoInst)
{
/* Run the Wine Gecko prompt */
Control_RunDLLW(hwndDlg, 0, L"appwiz.cpl install_gecko", SW_SHOW);
Control_RunDLLW(hwndDlg, 0, L"appwiz.cpl,,install_gecko", SW_SHOW);
}
/* Set title font */

View File

@ -1137,7 +1137,7 @@ list(APPEND SOURCE_MSVCRT
# qsort_s
# raise.c
# rand.c
# rand_s.c
rand_s.c
# realloc.c
# remove.c
# rename.c

View File

@ -0,0 +1,61 @@
/*
* PROJECT: ReactOS API Tests
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Tests for rand_s
* COPYRIGHT: Copyright 2024 Timo Kreuzer <timo.kreuzer@reactos.org>
*/
#include <apitest.h>
#include <stdio.h>
#ifdef TEST_STATIC_CRT
errno_t __cdecl rand_s(_Out_ unsigned int* _RandomValue);
#endif
typedef int __cdecl rand_s_t(unsigned int*);
rand_s_t *p_rand_s;
void test_rand_s_performance(void)
{
unsigned long long start, end;
unsigned int val;
int i;
start = __rdtsc();
for (i = 0; i < 10000; i++)
{
p_rand_s(&val);
}
end = __rdtsc();
printf("rand_s took %llu cycles\n", end - start);
}
START_TEST(rand_s)
{
unsigned int val;
int ret;
#ifndef TEST_STATIC_CRT
/* Dynamically load rand_s from mvcrt */
HMODULE msvcrt = GetModuleHandleA("msvcrt");
p_rand_s = (rand_s_t*)GetProcAddress(msvcrt, "rand_s");
if (!p_rand_s)
{
win_skip("rand_s is not available\n");
return;
}
#else
p_rand_s = rand_s;
#endif
/* Test performance */
test_rand_s_performance();
/* Test with NULL pointer */
ret = p_rand_s(NULL);
ok(ret == EINVAL, "Expected EINVAL, got %d\n", ret);
/* Test with valid pointer */
ret = p_rand_s(&val);
ok(ret == 0, "Expected 0, got %d\n", ret);
}

View File

@ -13,6 +13,7 @@ list(APPEND SOURCE_STATIC
fpcontrol.c
mbstowcs.c
mbtowc.c
rand_s.c
sprintf.c
strcpy.c
strlen.c

View File

@ -32,6 +32,7 @@ extern void func__vsnprintf(void);
extern void func__vsnwprintf(void);
extern void func_mbstowcs(void);
extern void func_mbtowc(void);
extern void func_rand_s(void);
extern void func_sprintf(void);
extern void func_strcpy(void);
extern void func_strlen(void);
@ -79,6 +80,7 @@ const struct test winetest_testlist[] =
{ "ceil", func_ceil },
{ "fabs", func_fabs },
{ "floor", func_floor },
{ "rand_s", func_rand_s },
#ifdef _M_AMD64 // x86 / arm need fixing
{ "fpcontrol", func_fpcontrol },
#endif

View File

@ -22,6 +22,7 @@ list(APPEND SOURCE
interlck.c
IsDBCSLeadByteEx.c
JapaneseCalendar.c
LCMapString.c
LoadLibraryExW.c
lstrcpynW.c
lstrlen.c

View File

@ -0,0 +1,60 @@
/*
* PROJECT: ReactOS api tests
* LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
* PURPOSE: Tests for LCMapString
* COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/
#include "precomp.h"
#undef ok_wstr_
static void
ok_wstr_(const char *file, int line, LPCWSTR x, LPCWSTR y)
{
char buf1[100], buf2[100];
lstrcpynA(buf1, wine_dbgstr_w(x), _countof(buf1));
lstrcpynA(buf2, wine_dbgstr_w(y), _countof(buf2));
ok_(file, line)(wcscmp(x, y) == 0, "Wrong string. Expected %s, got %s\n", buf2, buf1);
}
#undef ok_wstr
#define ok_wstr(x, y) ok_wstr_(__FILE__, __LINE__, x, y)
// "ABab12あアばバパ万萬" in UTF-16
static const WCHAR c_target[] =
L"ABab12\xff21\xff22\xff41\xff42\xff11\xff12\x3042\x30a2\x3070\x30d0\xff8a\xff9f\x4e07\x842c";
static void TEST_LCMapStringW(void)
{
WCHAR results[100];
LCMapStringW(0, LCMAP_FULLWIDTH, c_target, -1, results, _countof(results));
ok_wstr(results, L"\xff21\xff22\xff41\xff42\xff11\xff12\xff21\xff22\xff41\xff42\xff11\xff12\x3042\x30a2\x3070\x30d0\x30d1\x4e07\x842c");
LCMapStringW(0, LCMAP_HALFWIDTH, c_target, -1, results, _countof(results));
ok_wstr(results, L"ABab12ABab12\x3042\xff71\x3070\xff8a\xff9e\xff8a\xff9f\x4e07\x842c");
LCMapStringW(0, LCMAP_HIRAGANA, c_target, -1, results, _countof(results));
ok_wstr(results, L"ABab12\xff21\xff22\xff41\xff42\xff11\xff12\x3042\x3042\x3070\x3070\xff8a\xff9f\x4e07\x842c");
LCMapStringW(0, LCMAP_KATAKANA, c_target, -1, results, _countof(results));
ok_wstr(results, L"ABab12\xff21\xff22\xff41\xff42\xff11\xff12\x30a2\x30a2\x30d0\x30d0\xff8a\xff9f\x4e07\x842c");
LCMapStringW(0, LCMAP_LOWERCASE, c_target, -1, results, _countof(results));
ok_wstr(results, L"abab12\xff41\xff42\xff41\xff42\xff11\xff12\x3042\x30a2\x3070\x30d0\xff8a\xff9f\x4e07\x842c");
LCMapStringW(0, LCMAP_UPPERCASE, c_target, -1, results, _countof(results));
ok_wstr(results, L"ABAB12\xff21\xff22\xff21\xff22\xff11\xff12\x3042\x30a2\x3070\x30d0\xff8a\xff9f\x4e07\x842c");
LCMapStringW(0, LCMAP_SIMPLIFIED_CHINESE, c_target, -1, results, _countof(results));
ok_wstr(results, L"ABab12\xff21\xff22\xff41\xff42\xff11\xff12\x3042\x30a2\x3070\x30d0\xff8a\xff9f\x4e07\x4e07");
LCMapStringW(0, LCMAP_TRADITIONAL_CHINESE, c_target, -1, results, _countof(results));
ok_wstr(results, L"ABab12\xff21\xff22\xff41\xff42\xff11\xff12\x3042\x30a2\x3070\x30d0\xff8a\xff9f\x842c\x842c");
}
START_TEST(LCMapString)
{
TEST_LCMapStringW();
}

View File

@ -22,6 +22,7 @@ extern void func_InitOnce(void);
extern void func_interlck(void);
extern void func_IsDBCSLeadByteEx(void);
extern void func_JapaneseCalendar(void);
extern void func_LCMapString(void);
extern void func_LoadLibraryExW(void);
extern void func_lstrcpynW(void);
extern void func_lstrlen(void);
@ -59,6 +60,7 @@ const struct test winetest_testlist[] =
{ "interlck", func_interlck },
{ "IsDBCSLeadByteEx", func_IsDBCSLeadByteEx },
{ "JapaneseCalendar", func_JapaneseCalendar },
{ "LCMapString", func_LCMapString },
{ "LoadLibraryExW", func_LoadLibraryExW },
{ "lstrcpynW", func_lstrcpynW },
{ "lstrlen", func_lstrlen },

View File

@ -11,7 +11,6 @@
#include "shell32_apitest_sub.h"
#include <assert.h>
#define NUM_STAGE 4
#define NUM_STEP 8
#define NUM_CHECKS 12
#define INTERVAL 0
@ -89,24 +88,6 @@ static void TEST_Quit(void)
DoDeleteFilesAndDirs();
}
static BOOL FindSubProgram(void)
{
GetModuleFileNameW(NULL, s_szSubProgram, _countof(s_szSubProgram));
PathRemoveFileSpecW(s_szSubProgram);
PathAppendW(s_szSubProgram, L"shell32_apitest_sub.exe");
if (!PathFileExistsW(s_szSubProgram))
{
PathRemoveFileSpecW(s_szSubProgram);
PathAppendW(s_szSubProgram, L"testdata\\shell32_apitest_sub.exe");
if (!PathFileExistsW(s_szSubProgram))
return FALSE;
}
return TRUE;
}
static void DoBuildFilesAndDirs(void)
{
WCHAR szPath1[MAX_PATH];
@ -236,24 +217,10 @@ static void DoStepCheck(INT iStage, INT iStep, LPCSTR checks)
switch (iStage)
{
case 0:
{
static const TEST_ANSWER c_answers[] =
{
{ __LINE__, "000000010000010000000000" }, // 0
{ __LINE__, "000000040000000000000400" }, // 1
{ __LINE__, "000000000200020000000000" }, // 2
{ __LINE__, "000000000000080000000000" }, // 3
{ __LINE__, "000000000001010000000000" }, // 4
{ __LINE__, "000000000002020000000000" }, // 5
{ __LINE__, "000000000000000020000000" }, // 6
{ __LINE__, "000010000000100000000000" }, // 7
};
C_ASSERT(_countof(c_answers) == NUM_STEP);
lineno = c_answers[iStep].lineno;
answer = c_answers[iStep].answer;
break;
}
case 1:
case 3:
case 6:
case 9:
{
static const TEST_ANSWER c_answers[] =
{
@ -272,6 +239,27 @@ static void DoStepCheck(INT iStage, INT iStep, LPCSTR checks)
break;
}
case 2:
case 4:
case 5:
case 7:
{
static const TEST_ANSWER c_answers[] =
{
{ __LINE__, "000000000000000000000000" }, // 0
{ __LINE__, "000000000000000000000000" }, // 1
{ __LINE__, "000000000000000000000000" }, // 2
{ __LINE__, "000000000000000000000000" }, // 3
{ __LINE__, "000000000000000000000000" }, // 4
{ __LINE__, "000000000000000000000000" }, // 5
{ __LINE__, "000000000000000000000000" }, // 6
{ __LINE__, "000000000000000000000000" }, // 7
};
C_ASSERT(_countof(c_answers) == NUM_STEP);
lineno = c_answers[iStep].lineno;
answer = c_answers[iStep].answer;
break;
}
case 8:
{
static const TEST_ANSWER c_answers[] =
{
@ -279,8 +267,8 @@ static void DoStepCheck(INT iStage, INT iStep, LPCSTR checks)
{ __LINE__, "000000040000000000000400" }, // 1
{ __LINE__, "000000000200020000000000" }, // 2
{ __LINE__, "000000000000080000000000" }, // 3
{ __LINE__, "000000000001010000000000" }, // 4 // Recursive
{ __LINE__, "000000000002020000000000" }, // 5 // Recursive
{ __LINE__, "000000000001010000000000" }, // 4 // Recursive case
{ __LINE__, "000000000002020000000000" }, // 5 // Recursive case
{ __LINE__, "000000000000000020000000" }, // 6
{ __LINE__, "000010000000100000000000" }, // 7
};
@ -290,30 +278,13 @@ static void DoStepCheck(INT iStage, INT iStep, LPCSTR checks)
if (iStep == 4 || iStep == 5) // Recursive cases
{
if (lstrcmpA(checks, "000000000000000000000000") == 0)
{
trace("Warning! Recursive cases...\n");
answer = "000000000000000000000000";
else
trace("Warning\n");
}
}
break;
}
case 3:
{
static const TEST_ANSWER c_answers[] =
{
{ __LINE__, "000000010000010000000000" }, // 0
{ __LINE__, "000000040000000000000400" }, // 1
{ __LINE__, "000000000200020000000000" }, // 2
{ __LINE__, "000000000000080000000000" }, // 3
{ __LINE__, "000000000001010000000000" }, // 4 // Recursive
{ __LINE__, "000000000002020000000000" }, // 5 // Recursive
{ __LINE__, "000000000000000020000000" }, // 6
{ __LINE__, "000010000000100000000000" }, // 7
};
C_ASSERT(_countof(c_answers) == NUM_STEP);
lineno = c_answers[iStep].lineno;
answer = c_answers[iStep].answer;
break;
}
default:
{
assert(0);
@ -334,7 +305,7 @@ static DWORD WINAPI StageThreadFunc(LPVOID arg)
// 0: Create file1 in dir1
s_iStep = 0;
trace("Step %d\n", s_iStep);
::Sleep(1000); // Extra wait
SHChangeNotify(0, SHCNF_PATHW | SHCNF_FLUSH, NULL, NULL);
ZeroMemory(s_abChecks, sizeof(s_abChecks));
ret = DoCreateFile(s_szFile1InDir1);
ok_int(ret, TRUE);
@ -544,7 +515,7 @@ MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
static BOOL TEST_Init(void)
{
if (!FindSubProgram())
if (!FindSubProgram(s_szSubProgram, _countof(s_szSubProgram)))
{
skip("shell32_apitest_sub.exe not found\n");
return FALSE;

View File

@ -256,27 +256,6 @@ static WCHAR s_win_test_exe[MAX_PATH];
static WCHAR s_sys_bat_file[MAX_PATH];
static WCHAR s_cur_dir[MAX_PATH];
static BOOL
GetSubProgramPath(void)
{
GetModuleFileNameW(NULL, s_sub_program, _countof(s_sub_program));
PathRemoveFileSpecW(s_sub_program);
PathAppendW(s_sub_program, L"shell32_apitest_sub.exe");
if (!PathFileExistsW(s_sub_program))
{
PathRemoveFileSpecW(s_sub_program);
PathAppendW(s_sub_program, L"testdata\\shell32_apitest_sub.exe");
if (!PathFileExistsW(s_sub_program))
{
return FALSE;
}
}
return TRUE;
}
static const TEST_ENTRY s_entries_1[] =
{
// NULL
@ -462,11 +441,6 @@ static const TEST_ENTRY s_entries_1[] =
{ __LINE__, TRUE, TRUE, L"shell:::{450d8fba-ad25-11d0-98a8-0800361b1103}", NULL },
// shell:sendto
{ __LINE__, TRUE, TRUE, L"shell:sendto", NULL },
// iexplore.exe
{ __LINE__, TRUE, FALSE, L"iexplore", NULL },
{ __LINE__, TRUE, FALSE, L"iexplore.exe", NULL },
{ __LINE__, TRUE, TRUE, L"iexplore", NULL },
{ __LINE__, TRUE, TRUE, L"iexplore.exe", NULL },
// https://google.com
{ __LINE__, TRUE, FALSE, L"https://google.com", NULL },
{ __LINE__, TRUE, TRUE, L"https://google.com", NULL },
@ -677,7 +651,7 @@ START_TEST(ShellExecCmdLine)
}
}
if (!GetSubProgramPath())
if (!FindSubProgram(s_sub_program, _countof(s_sub_program)))
{
skip("shell32_apitest_sub.exe is not found\n");
return;

View File

@ -14,7 +14,9 @@
typedef enum DIRTYPE
{
DIRTYPE_DESKTOP = 0,
DIRTYPE_DESKTOP_DIR,
DIRTYPE_DRIVES,
DIRTYPE_PRINTERS,
DIRTYPE_DIR1,
DIRTYPE_MAX
} DIRTYPE;
@ -24,8 +26,6 @@ static LPITEMIDLIST s_pidl[DIRTYPE_MAX];
static UINT s_uRegID = 0;
static INT s_iStage = -1;
#define NUM_STAGE 4
#define EVENTS (SHCNE_CREATE | SHCNE_DELETE | SHCNE_MKDIR | SHCNE_RMDIR | \
SHCNE_RENAMEFOLDER | SHCNE_RENAMEITEM | SHCNE_UPDATEDIR | SHCNE_UPDATEITEM)
@ -40,11 +40,23 @@ inline LPITEMIDLIST DoGetPidl(INT iDir)
SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &ret);
break;
}
case DIRTYPE_DESKTOP_DIR:
{
WCHAR szPath1[MAX_PATH];
SHGetSpecialFolderPathW(NULL, szPath1, CSIDL_DESKTOPDIRECTORY, FALSE);
ret = ILCreateFromPathW(szPath1);
break;
}
case DIRTYPE_DRIVES:
{
SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &ret);
break;
}
case DIRTYPE_PRINTERS:
{
SHGetSpecialFolderLocation(NULL, CSIDL_PRINTERS, &ret);
break;
}
case DIRTYPE_DIR1:
{
WCHAR szPath1[MAX_PATH];
@ -85,8 +97,8 @@ static BOOL InitSHCN(HWND hwnd)
{
case 0:
{
entry.fRecursive = TRUE;
entry.pidl = s_pidl[DIRTYPE_DESKTOP];
entry.fRecursive = FALSE;
entry.pidl = NULL;
sources = SHCNRF_NewDelivery | SHCNRF_ShellLevel;
events = EVENTS;
break;
@ -94,7 +106,7 @@ static BOOL InitSHCN(HWND hwnd)
case 1:
{
entry.fRecursive = TRUE;
entry.pidl = s_pidl[DIRTYPE_DRIVES];
entry.pidl = NULL;
sources = SHCNRF_NewDelivery | SHCNRF_ShellLevel;
events = EVENTS;
break;
@ -102,12 +114,60 @@ static BOOL InitSHCN(HWND hwnd)
case 2:
{
entry.fRecursive = FALSE;
entry.pidl = s_pidl[DIRTYPE_DIR1];
entry.pidl = s_pidl[DIRTYPE_DESKTOP];
sources = SHCNRF_NewDelivery | SHCNRF_ShellLevel;
events = EVENTS;
break;
}
case 3:
{
entry.fRecursive = TRUE;
entry.pidl = s_pidl[DIRTYPE_DESKTOP];
sources = SHCNRF_NewDelivery | SHCNRF_ShellLevel;
events = EVENTS;
break;
}
case 4:
{
entry.fRecursive = TRUE;
entry.pidl = s_pidl[DIRTYPE_DESKTOP_DIR];
sources = SHCNRF_NewDelivery | SHCNRF_ShellLevel;
events = EVENTS;
break;
}
case 5:
{
entry.fRecursive = FALSE;
entry.pidl = s_pidl[DIRTYPE_DRIVES];
sources = SHCNRF_NewDelivery | SHCNRF_ShellLevel;
events = EVENTS;
break;
}
case 6:
{
entry.fRecursive = TRUE;
entry.pidl = s_pidl[DIRTYPE_DRIVES];
sources = SHCNRF_NewDelivery | SHCNRF_ShellLevel;
events = EVENTS;
break;
}
case 7:
{
entry.fRecursive = TRUE;
entry.pidl = s_pidl[DIRTYPE_PRINTERS];
sources = SHCNRF_NewDelivery | SHCNRF_ShellLevel;
events = EVENTS;
break;
}
case 8:
{
entry.fRecursive = FALSE;
entry.pidl = s_pidl[DIRTYPE_DIR1];
sources = SHCNRF_NewDelivery | SHCNRF_ShellLevel;
events = EVENTS;
break;
}
case 9:
{
entry.fRecursive = TRUE;
entry.pidl = s_pidl[DIRTYPE_DIR1];
@ -293,13 +353,19 @@ wWinMain(
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wc.lpszClassName = SUB_CLASSNAME;
if (!RegisterClassW(&wc))
{
assert(0);
return -1;
}
HWND hwnd = CreateWindowW(SUB_CLASSNAME, SUB_CLASSNAME, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 400, 100,
NULL, NULL, hInstance, NULL);
if (!hwnd)
{
assert(0);
return -2;
}
ShowWindow(hwnd, SW_SHOWNORMAL);
UpdateWindow(hwnd);

View File

@ -10,6 +10,26 @@
#define WM_SHELL_NOTIFY (WM_USER + 100)
#define NUM_STAGE 10
static inline BOOL FindSubProgram(LPWSTR pszSubProgram, DWORD cchSubProgram)
{
GetModuleFileNameW(NULL, pszSubProgram, cchSubProgram);
PathRemoveFileSpecW(pszSubProgram);
PathAppendW(pszSubProgram, L"shell32_apitest_sub.exe");
if (!PathFileExistsW(pszSubProgram))
{
PathRemoveFileSpecW(pszSubProgram);
PathAppendW(pszSubProgram, L"testdata\\shell32_apitest_sub.exe");
if (!PathFileExistsW(pszSubProgram))
return FALSE;
}
return TRUE;
}
static inline HWND DoWaitForWindow(LPCWSTR clsname, LPCWSTR text, BOOL bClosing, BOOL bForce)
{
HWND hwnd = NULL;

View File

@ -54,7 +54,12 @@ extern "C" {
#define _CRT_TERMINATE_DEFINED
__declspec(noreturn) void __cdecl exit(_In_ int _Code);
_CRTIMP __declspec(noreturn) void __cdecl _exit(_In_ int _Code);
#if !defined __NO_ISOCEXT /* extern stub in static libmingwex.a */
/* C99 function name */
__declspec(noreturn) void __cdecl _Exit(int); /* Declare to get noreturn attribute. */
__CRT_INLINE void __cdecl _Exit(int status)
{ _exit(status); }
#endif
#if __MINGW_GNUC_PREREQ(4,4)
#pragma push_macro("abort")
#undef abort
@ -62,7 +67,6 @@ extern "C" {
__declspec(noreturn) void __cdecl abort(void);
#if __MINGW_GNUC_PREREQ(4,4)
#pragma pop_macro("abort")
#undef abort
#endif
#endif

View File

@ -120,7 +120,6 @@ typedef struct _SOUND_OVERLAPPED
OVERLAPPED Standard;
struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance;
PWAVEHDR Header;
BOOL PerformCompletion;
LPOVERLAPPED_COMPLETION_ROUTINE OriginalCompletionRoutine;
PVOID CompletionContext;

View File

@ -240,17 +240,12 @@ list(APPEND CRT_MATH_SOURCE
math/ldiv.c
math/logf.c
math/powf.c
math/rand.c
)
list(APPEND CRT_MATH_ASM_SOURCE
${LIBCNTPR_MATH_ASM_SOURCE}
)
list(APPEND LIBCNTPR_MATH_SOURCE
math/rand_nt.c
)
if(ARCH STREQUAL "i386")
list(APPEND ATAN2_ASM_SOURCE math/i386/atan2_asm.s)
elseif(ARCH STREQUAL "amd64")

View File

@ -1,73 +0,0 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <precomp.h>
#include <ntsecapi.h>
#include <internal/tls.h>
/*
* @implemented
*/
int
rand(void)
{
thread_data_t *data = msvcrt_get_thread_data();
/* this is the algorithm used by MSVC, according to
* http://en.wikipedia.org/wiki/List_of_pseudorandom_number_generators */
data->random_seed = data->random_seed * 214013 + 2531011;
return (data->random_seed >> 16) & RAND_MAX;
}
/*
* @implemented
*/
void
srand(unsigned int seed)
{
thread_data_t *data = msvcrt_get_thread_data();
data->random_seed = seed;
}
/*********************************************************************
* rand_s (MSVCRT.@)
*/
int CDECL rand_s(unsigned int *pval)
{
BOOLEAN (WINAPI *pSystemFunction036)(PVOID, ULONG); // RtlGenRandom
HINSTANCE hadvapi32;
if (!pval)
{
_invalid_parameter(NULL,_CRT_WIDE("rand_s"),_CRT_WIDE(__FILE__),__LINE__, 0);
*_errno() = EINVAL;
return EINVAL;
}
*pval = 0;
hadvapi32 = LoadLibraryA("advapi32.dll");
if (!hadvapi32)
{
_invalid_parameter(NULL,_CRT_WIDE("rand_s"),_CRT_WIDE(__FILE__),__LINE__, 0);
*_errno() = EINVAL;
return EINVAL;
}
pSystemFunction036 = (void*)GetProcAddress(hadvapi32, "SystemFunction036");
if (!pSystemFunction036)
{
_invalid_parameter(NULL,_CRT_WIDE("rand_s"),_CRT_WIDE(__FILE__),__LINE__, 0);
*_errno() = EINVAL;
FreeLibrary(hadvapi32);
return EINVAL;
}
if (!pSystemFunction036(pval, sizeof(*pval)))
{
_invalid_parameter(NULL,_CRT_WIDE("rand_s"),_CRT_WIDE(__FILE__),__LINE__, 0);
*_errno() = EINVAL;
FreeLibrary(hadvapi32);
return EINVAL;
}
FreeLibrary(hadvapi32);
return 0;
}

View File

@ -11,6 +11,13 @@ list(APPEND MSVCRTEX_SOURCE
misc/ofmt_stub.c
stdio/acrt_iob_func.c)
if(DLL_EXPORT_VERSION LESS 0x600)
list(APPEND MSVCRTEX_SOURCE
stdlib/_invalid_parameter.c
stdlib/rand_s.c
)
endif()
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
# Clang performs some optimizations requiring those funtions
list(APPEND MSVCRTEX_SOURCE

View File

@ -0,0 +1,52 @@
/*
* PROJECT: ReactOS CRT library
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: _invalid_parameter implementation
* COPYRIGHT: Timo Kreuzer <timo.kreuzer@reactos.org>
*/
#include <precomp.h>
#ifdef _MSVCRTEX_
#undef TRACE
#undef ERR
#define TRACE(...)
#define ERR(...)
#endif
static _invalid_parameter_handler invalid_parameter_handler = NULL;
/******************************************************************************
* _invalid_parameter (MSVCRT.@)
*/
void __cdecl _invalid_parameter(const wchar_t *expr, const wchar_t *func,
const wchar_t *file, unsigned int line, uintptr_t arg)
{
if (invalid_parameter_handler) invalid_parameter_handler( expr, func, file, line, arg );
else
{
ERR( "%s:%u %s: %s %lx\n", debugstr_w(file), line, debugstr_w(func), debugstr_w(expr), arg );
#if _MSVCR_VER > 0 // FIXME: possible improvement: use a global variable in the DLL
RaiseException( STATUS_INVALID_CRUNTIME_PARAMETER, EXCEPTION_NONCONTINUABLE, 0, NULL );
#endif
}
}
/* _get_invalid_parameter_handler - not exported in native msvcrt, added in msvcr80 */
_invalid_parameter_handler CDECL _get_invalid_parameter_handler(void)
{
TRACE("\n");
return invalid_parameter_handler;
}
/* _set_invalid_parameter_handler - not exproted in native msvcrt, added in msvcr80 */
_invalid_parameter_handler CDECL _set_invalid_parameter_handler(
_invalid_parameter_handler handler)
{
_invalid_parameter_handler old = invalid_parameter_handler;
TRACE("(%p)\n", handler);
invalid_parameter_handler = handler;
return old;
}

View File

@ -11,8 +11,6 @@
#include <errno.h>
#include <internal/wine/msvcrt.h>
static _invalid_parameter_handler invalid_parameter_handler = NULL;
/*********************************************************************
* _errno (MSVCRT.@)
*/
@ -130,38 +128,3 @@ void CDECL _seterrormode(int mode)
{
SetErrorMode( mode );
}
/******************************************************************************
* _invalid_parameter (MSVCRT.@)
*/
void __cdecl _invalid_parameter(const wchar_t *expr, const wchar_t *func,
const wchar_t *file, unsigned int line, uintptr_t arg)
{
if (invalid_parameter_handler) invalid_parameter_handler( expr, func, file, line, arg );
else
{
ERR( "%s:%u %s: %s %lx\n", debugstr_w(file), line, debugstr_w(func), debugstr_w(expr), arg );
#if _MSVCR_VER > 0 // FIXME: possible improvement: use a global variable in the DLL
RaiseException( STATUS_INVALID_CRUNTIME_PARAMETER, EXCEPTION_NONCONTINUABLE, 0, NULL );
#endif
}
}
/* _get_invalid_parameter_handler - not exported in native msvcrt, added in msvcr80 */
_invalid_parameter_handler CDECL _get_invalid_parameter_handler(void)
{
TRACE("\n");
return invalid_parameter_handler;
}
/* _set_invalid_parameter_handler - not exproted in native msvcrt, added in msvcr80 */
_invalid_parameter_handler CDECL _set_invalid_parameter_handler(
_invalid_parameter_handler handler)
{
_invalid_parameter_handler old = invalid_parameter_handler;
TRACE("(%p)\n", handler);
invalid_parameter_handler = handler;
return old;
}

28
sdk/lib/crt/stdlib/rand.c Normal file
View File

@ -0,0 +1,28 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <precomp.h>
#include <ntsecapi.h>
#include <internal/tls.h>
/*
* @implemented
*/
int
rand(void)
{
thread_data_t *data = msvcrt_get_thread_data();
/* this is the algorithm used by MSVC, according to
* http://en.wikipedia.org/wiki/List_of_pseudorandom_number_generators */
data->random_seed = data->random_seed * 214013 + 2531011;
return (data->random_seed >> 16) & RAND_MAX;
}
/*
* @implemented
*/
void
srand(unsigned int seed)
{
thread_data_t *data = msvcrt_get_thread_data();
data->random_seed = seed;
}

View File

@ -0,0 +1,72 @@
/*
* PROJECT: ReactOS CRT library
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: rand_s implementation
* COPYRIGHT: Copyright 2010 Sylvain Petreolle <spetreolle@yahoo.fr>
* Copyright 2015 Christoph von Wittich <christoph_vw@reactos.org>
* Copyright 2015 Pierre Schweitzer <pierre@reactos.org>
*/
#include <precomp.h>
typedef BOOLEAN (WINAPI *PFN_SystemFunction036)(PVOID, ULONG); // RtlGenRandom
PFN_SystemFunction036 g_pfnSystemFunction036 = NULL;
/*********************************************************************
* rand_s (MSVCRT.@)
*/
int CDECL rand_s(unsigned int *pval)
{
HINSTANCE hadvapi32;
if (!pval)
{
_invalid_parameter(NULL,_CRT_WIDE("rand_s"),_CRT_WIDE(__FILE__),__LINE__, 0);
*_errno() = EINVAL;
return EINVAL;
}
*pval = 0;
if (g_pfnSystemFunction036 == NULL)
{
PFN_SystemFunction036 pSystemFunction036;
hadvapi32 = LoadLibraryA("advapi32.dll");
if (!hadvapi32)
{
_invalid_parameter(NULL,_CRT_WIDE("rand_s"),_CRT_WIDE(__FILE__),__LINE__, 0);
*_errno() = EINVAL;
return EINVAL;
}
pSystemFunction036 = (void*)GetProcAddress(hadvapi32, "SystemFunction036");
if (!pSystemFunction036)
{
_invalid_parameter(NULL,_CRT_WIDE("rand_s"),_CRT_WIDE(__FILE__),__LINE__, 0);
*_errno() = EINVAL;
FreeLibrary(hadvapi32);
return EINVAL;
}
g_pfnSystemFunction036 = pSystemFunction036;
}
if (!g_pfnSystemFunction036(pval, sizeof(*pval)))
{
_invalid_parameter(NULL,_CRT_WIDE("rand_s"),_CRT_WIDE(__FILE__),__LINE__, 0);
*_errno() = EINVAL;
return EINVAL;
}
return 0;
}
// Small hack: import stub to allow GCC's stdc++ to link
#if defined(__GNUC__) && (DLL_EXPORT_VERSION < 0x600)
#ifdef WIN64
const void* __imp_rand_s = rand_s;
#else
const void* _imp_rand_s = rand_s;
#endif
#endif

View File

@ -1,11 +1,17 @@
list(APPEND LIBCNTPR_STDLIB_SOURCE
list(APPEND COMMON_STDLIB_SOURCE
stdlib/qsort.c
)
list(APPEND LIBCNTPR_STDLIB_SOURCE
${COMMON_STDLIB_SOURCE}
stdlib/rand_nt.c
)
list(APPEND CRT_STDLIB_SOURCE
${LIBCNTPR_STDLIB_SOURCE}
${COMMON_STDLIB_SOURCE}
stdlib/_exit.c
stdlib/_invalid_parameter.c
stdlib/_set_abort_behavior.c
stdlib/abort.c
stdlib/atexit.c
@ -22,6 +28,8 @@ list(APPEND CRT_STDLIB_SOURCE
stdlib/mbstowcs.c
stdlib/obsol.c
stdlib/putenv.c
stdlib/rand.c
stdlib/rand_s.c
stdlib/rot.c
stdlib/senv.c
stdlib/swab.c

View File

@ -26,7 +26,7 @@ Unsupported MME messages:
* Any not mentioned above
Notes/Bugs:
* WHDR_BEGINLOOP and WHDR_ENDLOOP are ignored
* WHDR_BEGINLOOP and WHDR_ENDLOOP are not working for looping multiple wave headers, only for a single header.
* Not possible to pause/restart playback

View File

@ -10,7 +10,6 @@
#include "precomp.h"
/*
DoWaveStreaming
Check if there is streaming to be done, and if so, do it.
@ -54,6 +53,22 @@ DoWaveStreaming(
return;
}
/* Do we need to loop a header? */
if (DeviceType == WAVE_OUT_DEVICE_TYPE && (Header->dwFlags & WHDR_BEGINLOOP))
{
if ((Header->dwFlags & WHDR_ENDLOOP))
{
/* Get loop count */
SoundDeviceInstance->LoopsRemaining = Header->dwLoops;
}
else
{
/* Report and help notice such a case */
SND_WARN(L"Looping multiple headers is UNIMPLEMENTED. Will play once only\n");
SND_ASSERT((Header->dwFlags & (WHDR_BEGINLOOP | WHDR_ENDLOOP)) == (WHDR_BEGINLOOP | WHDR_ENDLOOP));
}
}
while ( ( SoundDeviceInstance->OutstandingBuffers < SoundDeviceInstance->BufferCount ) &&
( Header ) && SoundDeviceInstance->ResetInProgress == FALSE)
{
@ -106,10 +121,6 @@ DoWaveStreaming(
Overlap->SoundDeviceInstance = SoundDeviceInstance;
Overlap->Header = Header;
/* Don't complete this header if it's part of a loop */
Overlap->PerformCompletion = TRUE;
// ( SoundDeviceInstance->LoopsRemaining > 0 );
/* Adjust the commit-related counters */
HeaderExtension->BytesCommitted += BytesToCommit;
++ SoundDeviceInstance->OutstandingBuffers;
@ -189,8 +200,8 @@ CompleteIO(
-- SoundDeviceInstance->OutstandingBuffers;
/* Did we finish a WAVEHDR and aren't looping? */
if ( HdrExtension->BytesCompleted + dwNumberOfBytesTransferred >= WaveHdr->dwBufferLength &&
SoundOverlapped->PerformCompletion )
if (HdrExtension->BytesCompleted + dwNumberOfBytesTransferred >= WaveHdr->dwBufferLength &&
SoundDeviceInstance->LoopsRemaining == 0)
{
/* Wave buffer fully completed */
Bytes = WaveHdr->dwBufferLength - HdrExtension->BytesCompleted;
@ -203,9 +214,24 @@ CompleteIO(
}
else
{
/* Partially completed */
HdrExtension->BytesCompleted += dwNumberOfBytesTransferred;
SND_TRACE(L"%d/%d bytes of wavehdr completed\n", HdrExtension->BytesCompleted, WaveHdr->dwBufferLength);
/* Do we loop a header? */
if (HdrExtension->BytesCommitted == WaveHdr->dwBufferLength &&
SoundDeviceInstance->LoopsRemaining != 0)
{
/* Reset amount of bytes and decrement loop count, to play next iteration */
HdrExtension->BytesCommitted = 0;
if (SoundDeviceInstance->LoopsRemaining != INFINITE)
--SoundDeviceInstance->LoopsRemaining;
SND_TRACE(L"Looping the header, remaining loops %u\n", SoundDeviceInstance->LoopsRemaining);
}
else
{
/* Partially completed */
HdrExtension->BytesCompleted += dwNumberOfBytesTransferred;
SND_TRACE(L"%u/%u bytes of wavehdr completed\n", HdrExtension->BytesCompleted, WaveHdr->dwBufferLength);
}
break;
}

View File

@ -341,6 +341,9 @@ IntDeactivateWindow(PTHREADINFO pti, HANDLE tid)
UserDerefObjectCo(pwndFocus);
}
/* Check for keyboard modifiers and release them (CORE-14768) */
MsqReleaseModifierKeys(pti->MessageQueue);
if (InAAPM) pti->TIF_flags &= ~TIF_INACTIVATEAPPMSG;
if (ptiCurrent != pti)
{

View File

@ -2530,6 +2530,21 @@ MsqSetStateWindow(PTHREADINFO pti, ULONG Type, HWND hWnd)
return NULL;
}
VOID FASTCALL
MsqReleaseModifierKeys(PUSER_MESSAGE_QUEUE MessageQueue)
{
WORD ModifierKeys[] = { VK_LCONTROL, VK_RCONTROL, VK_CONTROL,
VK_LMENU, VK_RMENU, VK_MENU,
VK_LSHIFT, VK_RSHIFT, VK_SHIFT };
UINT i;
for (i = 0; i < _countof(ModifierKeys); ++i)
{
if (IS_KEY_DOWN(MessageQueue->afKeyState, ModifierKeys[i]))
SET_KEY_DOWN(MessageQueue->afKeyState, ModifierKeys[i], FALSE);
}
}
SHORT
APIENTRY
NtUserGetKeyState(INT key)

View File

@ -288,4 +288,7 @@ co_IntWaitMessage( PWND Window,
UINT MsgFilterMin,
UINT MsgFilterMax );
VOID FASTCALL
MsqReleaseModifierKeys(PUSER_MESSAGE_QUEUE MessageQueue);
/* EOF */