Wine-Devel
Threads by month
- ----- 2026 -----
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- 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
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 4 participants
- 84544 discussions
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/riched20/writer.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/riched20/writer.c b/dlls/riched20/writer.c
index 9e79eda274d..98ae352ab7b 100644
--- a/dlls/riched20/writer.c
+++ b/dlls/riched20/writer.c
@@ -1148,7 +1148,8 @@ static BOOL ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream,
nChars -= nLen;
cursor.nOffset = 0;
- cursor.pRun = ME_FindItemFwd(cursor.pRun, diRun);
+ cursor.pRun = run_next_all_paras( &cursor.pRun->member.run ) ?
+ run_get_di( run_next_all_paras( &cursor.pRun->member.run ) ) : NULL;
}
heap_free(buffer);
--
2.23.0
1
0
Oct. 28, 2020
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/riched20/paint.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c
index d3bbbc9d672..d15c47b72aa 100644
--- a/dlls/riched20/paint.c
+++ b/dlls/riched20/paint.c
@@ -846,7 +846,7 @@ static void draw_table_borders( ME_Context *c, ME_Paragraph *para )
rowY = c->pt.y + para->pt.y;
if (para->fmt.dwMask & PFM_SPACEBEFORE)
rowY += ME_twips2pointsY(c, para->fmt.dySpaceBefore);
- nHeight = ME_FindItemFwd( para_get_di( para ), diStartRow )->member.row.nHeight;
+ nHeight = para_first_row( para )->nHeight;
rowBottom = rowY + nHeight;
/* Draw horizontal lines */
--
2.23.0
1
0
[PATCH 1/5] riched20: Pass para ptrs to the various para selection functions.
by Huw Davies Oct. 28, 2020
by Huw Davies Oct. 28, 2020
Oct. 28, 2020
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/riched20/caret.c | 2 +-
dlls/riched20/editor.c | 14 +++---
dlls/riched20/editor.h | 8 ++--
dlls/riched20/editstr.h | 2 +-
dlls/riched20/paint.c | 48 ++++++++++---------
dlls/riched20/para.c | 100 ++++++++++++++++++++--------------------
dlls/riched20/reader.c | 2 +-
7 files changed, 90 insertions(+), 86 deletions(-)
diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c
index 47fe77df922..8af0f1de724 100644
--- a/dlls/riched20/caret.c
+++ b/dlls/riched20/caret.c
@@ -433,7 +433,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start,
continue;
}
}
- if (delete_all) ME_SetDefaultParaFormat( editor, &start_para->fmt );
+ if (delete_all) editor_set_default_para_fmt( editor, &start_para->fmt );
return TRUE;
}
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index 462245db233..d06693232ab 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -678,7 +678,7 @@ void ME_RTFParAttrHook(RTF_Info *info)
{
PARAFORMAT2 fmt;
fmt.cbSize = sizeof(fmt);
- ME_GetSelectionParaFormat(info->editor, &fmt);
+ editor_get_selection_para_fmt( info->editor, &fmt );
info->fmt.dwMask |= PFM_STARTINDENT | PFM_OFFSET;
info->fmt.dxStartIndent = fmt.dxStartIndent;
info->fmt.dxOffset = fmt.dxOffset;
@@ -713,7 +713,7 @@ void ME_RTFParAttrHook(RTF_Info *info)
{
PARAFORMAT2 fmt;
fmt.cbSize = sizeof(fmt);
- ME_GetSelectionParaFormat(info->editor, &fmt);
+ editor_get_selection_para_fmt( info->editor, &fmt );
memcpy(info->fmt.rgxTabs, fmt.rgxTabs,
fmt.cTabCount * sizeof(fmt.rgxTabs[0]));
info->fmt.cTabCount = fmt.cTabCount;
@@ -1637,7 +1637,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
ME_GetTextLength(editor), FALSE);
from = to = 0;
ME_ClearTempStyle(editor);
- ME_SetDefaultParaFormat(editor, &editor->pCursors[0].pPara->member.para.fmt);
+ editor_set_default_para_fmt( editor, &editor->pCursors[0].pPara->member.para.fmt );
}
@@ -2533,7 +2533,7 @@ static BOOL handle_enter(ME_TextEditor *editor)
ME_InsertTextFromCursor(editor, 0, &endl, 1,
editor->pCursors[0].pRun->member.run.style);
para = editor->pBuffer->pFirst->member.para.next_para;
- ME_SetDefaultParaFormat(editor, ¶->member.para.fmt);
+ editor_set_default_para_fmt( editor, ¶->member.para.fmt );
para->member.para.nFlags = 0;
para_mark_rewrap( editor, ¶->member.para );
editor->pCursors[0].pPara = para;
@@ -3131,7 +3131,7 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10)
ed->nUndoMode = umAddToUndo;
ed->nParagraphs = 1;
ed->nLastSelStart = ed->nLastSelEnd = 0;
- ed->pLastSelStartPara = ed->pLastSelEndPara = ed->pCursors[0].pPara;
+ ed->last_sel_start_para = ed->last_sel_end_para = &ed->pCursors[0].pPara->member.para;
ed->bHideSelection = FALSE;
ed->pfnWordBreak = NULL;
ed->lpOleCallback = NULL;
@@ -4027,14 +4027,14 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
}
case EM_SETPARAFORMAT:
{
- BOOL result = ME_SetSelectionParaFormat(editor, (PARAFORMAT2 *)lParam);
+ BOOL result = editor_set_selection_para_fmt( editor, (PARAFORMAT2 *)lParam );
ME_WrapMarkedParagraphs(editor);
ME_UpdateScrollBar(editor);
ME_CommitUndo(editor);
return result;
}
case EM_GETPARAFORMAT:
- ME_GetSelectionParaFormat(editor, (PARAFORMAT2 *)lParam);
+ editor_get_selection_para_fmt( editor, (PARAFORMAT2 *)lParam );
return ((PARAFORMAT2 *)lParam)->dwMask;
case EM_GETFIRSTVISIBLELINE:
{
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index 1a2346854e7..ddb6d138957 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -204,15 +204,15 @@ void para_range_invalidate( ME_TextEditor *editor, ME_Paragraph *start_para, ME_
void ME_SendRequestResize(ME_TextEditor *editor, BOOL force) DECLSPEC_HIDDEN;
/* para.c */
+void editor_get_selection_paras(ME_TextEditor *editor, ME_Paragraph **para, ME_Paragraph **para_end ) DECLSPEC_HIDDEN;
+void editor_get_selection_para_fmt( ME_TextEditor *editor, PARAFORMAT2 *fmt ) DECLSPEC_HIDDEN;
+void editor_set_default_para_fmt(ME_TextEditor *editor, PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN;
+BOOL editor_set_selection_para_fmt( ME_TextEditor *editor, const PARAFORMAT2 *fmt ) DECLSPEC_HIDDEN;
ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *run) DECLSPEC_HIDDEN;
-void ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end) DECLSPEC_HIDDEN;
void ME_MakeFirstParagraph(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_DumpParaStyle(ME_Paragraph *s) DECLSPEC_HIDDEN;
void ME_DumpParaStyleToBuf(const PARAFORMAT2 *pFmt, char buf[2048]) DECLSPEC_HIDDEN;
-BOOL ME_SetSelectionParaFormat(ME_TextEditor *editor, const PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN;
-void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN;
void ME_MarkAllForWrapping(ME_TextEditor *editor) DECLSPEC_HIDDEN;
-void ME_SetDefaultParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN;
int get_total_width(ME_TextEditor *editor) DECLSPEC_HIDDEN;
ME_Cell *para_cell( ME_Paragraph *para ) DECLSPEC_HIDDEN;
void para_destroy( ME_TextEditor *editor, ME_Paragraph *item ) DECLSPEC_HIDDEN;
diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h
index 8722890bf47..bd839afb0c0 100644
--- a/dlls/riched20/editstr.h
+++ b/dlls/riched20/editstr.h
@@ -407,7 +407,7 @@ typedef struct tagME_TextEditor
ME_UndoMode nUndoMode;
int nParagraphs;
int nLastSelStart, nLastSelEnd;
- ME_DisplayItem *pLastSelStartPara, *pLastSelEndPara;
+ ME_Paragraph *last_sel_start_para, *last_sel_end_para;
ME_FontCacheItem pFontCache[HFONT_CACHE_SIZE];
int nZoomNumerator, nZoomDenominator;
RECT prevClientRect;
diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c
index 180307ae01b..d3bbbc9d672 100644
--- a/dlls/riched20/paint.c
+++ b/dlls/riched20/paint.c
@@ -1312,8 +1312,8 @@ void editor_ensure_visible( ME_TextEditor *editor, ME_Cursor *cursor )
void
ME_InvalidateSelection(ME_TextEditor *editor)
{
- ME_DisplayItem *sel_start, *sel_end;
- ME_DisplayItem *repaint_start = NULL, *repaint_end = NULL;
+ ME_Paragraph *sel_start, *sel_end;
+ ME_Paragraph *repaint_start = NULL, *repaint_end = NULL;
int nStart, nEnd;
int len = ME_GetTextLength(editor);
@@ -1323,41 +1323,47 @@ ME_InvalidateSelection(ME_TextEditor *editor)
if (nStart == nEnd && editor->nLastSelStart == editor->nLastSelEnd)
return;
ME_WrapMarkedParagraphs(editor);
- ME_GetSelectionParas(editor, &sel_start, &sel_end);
- assert(sel_start->type == diParagraph);
- assert(sel_end->type == diParagraph);
+ editor_get_selection_paras( editor, &sel_start, &sel_end );
+
/* last selection markers aren't always updated, which means
* they can point past the end of the document */
- if (editor->nLastSelStart > len || editor->nLastSelEnd > len) {
- repaint_start = ME_FindItemFwd(editor->pBuffer->pFirst, diParagraph);
- repaint_end = editor->pBuffer->pLast->member.para.prev_para;
- } else {
+ if (editor->nLastSelStart > len || editor->nLastSelEnd > len)
+ {
+ repaint_start = editor_first_para( editor );
+ repaint_end = para_prev( editor_end_para( editor ) );
+ }
+ else
+ {
/* if the start part of selection is being expanded or contracted... */
- if (nStart < editor->nLastSelStart) {
+ if (nStart < editor->nLastSelStart)
+ {
repaint_start = sel_start;
- repaint_end = editor->pLastSelStartPara;
- } else if (nStart > editor->nLastSelStart) {
- repaint_start = editor->pLastSelStartPara;
+ repaint_end = editor->last_sel_start_para;
+ }
+ else if (nStart > editor->nLastSelStart)
+ {
+ repaint_start = editor->last_sel_start_para;
repaint_end = sel_start;
}
/* if the end part of selection is being contracted or expanded... */
- if (nEnd < editor->nLastSelEnd) {
+ if (nEnd < editor->nLastSelEnd)
+ {
if (!repaint_start) repaint_start = sel_end;
- repaint_end = editor->pLastSelEndPara;
- } else if (nEnd > editor->nLastSelEnd) {
- if (!repaint_start) repaint_start = editor->pLastSelEndPara;
+ repaint_end = editor->last_sel_end_para;
+ }
+ else if (nEnd > editor->nLastSelEnd)
+ {
+ if (!repaint_start) repaint_start = editor->last_sel_end_para;
repaint_end = sel_end;
}
}
if (repaint_start)
- para_range_invalidate( editor, &repaint_start->member.para, &repaint_end->member.para );
+ para_range_invalidate( editor, repaint_start, repaint_end );
/* remember the last invalidated position */
ME_GetSelectionOfs(editor, &editor->nLastSelStart, &editor->nLastSelEnd);
- ME_GetSelectionParas(editor, &editor->pLastSelStartPara, &editor->pLastSelEndPara);
- assert(editor->pLastSelStartPara->type == diParagraph);
- assert(editor->pLastSelEndPara->type == diParagraph);
+ editor_get_selection_paras( editor, &editor->last_sel_start_para, &editor->last_sel_end_para );
}
BOOL
diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c
index c7a0e271510..4348530bbdb 100644
--- a/dlls/riched20/para.c
+++ b/dlls/riched20/para.c
@@ -33,7 +33,7 @@ static ME_Paragraph *para_create( ME_TextEditor *editor )
{
ME_DisplayItem *item = ME_MakeDI(diParagraph);
- ME_SetDefaultParaFormat(editor, &item->member.para.fmt);
+ editor_set_default_para_fmt( editor, &item->member.para.fmt );
item->member.para.nFlags = MEPF_REWRAP;
return &item->member.para;
@@ -459,7 +459,7 @@ static void para_num_clear_list( ME_TextEditor *editor, ME_Paragraph *para, cons
} while (para_num_same_list( ¶->fmt, orig_fmt ));
}
-static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_Paragraph *para, const PARAFORMAT2 *pFmt)
+static BOOL para_set_fmt( ME_TextEditor *editor, ME_Paragraph *para, const PARAFORMAT2 *pFmt )
{
PARAFORMAT2 copy;
DWORD dwMask;
@@ -782,10 +782,10 @@ ME_Paragraph *para_join( ME_TextEditor *editor, ME_Paragraph *para, BOOL use_fir
ME_Remove( run_get_di( end_run ) );
ME_DestroyDisplayItem( run_get_di( end_run) );
- if (editor->pLastSelStartPara == para_get_di( next ))
- editor->pLastSelStartPara = para_get_di( para );
- if (editor->pLastSelEndPara == para_get_di( next ))
- editor->pLastSelEndPara = para_get_di( para );
+ if (editor->last_sel_start_para == next)
+ editor->last_sel_start_para = para;
+ if (editor->last_sel_end_para == next)
+ editor->last_sel_end_para = para;
para->next_para = next->next_para;
next->next_para->member.para.prev_para = para_get_di( para );
@@ -868,18 +868,18 @@ void ME_DumpParaStyleToBuf(const PARAFORMAT2 *pFmt, char buf[2048])
#undef DUMP_EFFECT
}
-void
-ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end)
+void editor_get_selection_paras( ME_TextEditor *editor, ME_Paragraph **para, ME_Paragraph **para_end )
{
ME_Cursor *pEndCursor = &editor->pCursors[1];
- *para = editor->pCursors[0].pPara;
- *para_end = editor->pCursors[1].pPara;
+ *para = &editor->pCursors[0].pPara->member.para;
+ *para_end = &editor->pCursors[1].pPara->member.para;
if (*para == *para_end)
return;
- if ((*para_end)->member.para.nCharOfs < (*para)->member.para.nCharOfs) {
- ME_DisplayItem *tmp = *para;
+ if ((*para_end)->nCharOfs < (*para)->nCharOfs)
+ {
+ ME_Paragraph *tmp = *para;
*para = *para_end;
*para_end = tmp;
@@ -889,79 +889,77 @@ ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayIte
/* The paragraph at the end of a non-empty selection isn't included
* if the selection ends at the start of the paragraph. */
if (!pEndCursor->pRun->member.run.nCharOfs && !pEndCursor->nOffset)
- *para_end = (*para_end)->member.para.prev_para;
+ *para_end = para_prev( *para_end );
}
-BOOL ME_SetSelectionParaFormat(ME_TextEditor *editor, const PARAFORMAT2 *pFmt)
+BOOL editor_set_selection_para_fmt( ME_TextEditor *editor, const PARAFORMAT2 *fmt )
{
- ME_DisplayItem *para, *para_end;
+ ME_Paragraph *para, *para_end;
- ME_GetSelectionParas(editor, ¶, ¶_end);
+ editor_get_selection_paras( editor, ¶, ¶_end );
- do {
- ME_SetParaFormat(editor, ¶->member.para, pFmt);
- if (para == para_end)
- break;
- para = para->member.para.next_para;
- } while(1);
+ do
+ {
+ para_set_fmt( editor, para, fmt );
+ if (para == para_end) break;
+ para = para_next( para );
+ } while(1);
- return TRUE;
+ return TRUE;
}
-static void ME_GetParaFormat(ME_TextEditor *editor,
- const ME_DisplayItem *para,
- PARAFORMAT2 *pFmt)
+static void para_copy_fmt( const ME_Paragraph *para, PARAFORMAT2 *fmt )
{
- UINT cbSize = pFmt->cbSize;
- if (pFmt->cbSize >= sizeof(PARAFORMAT2)) {
- *pFmt = para->member.para.fmt;
- } else {
- CopyMemory(pFmt, ¶->member.para.fmt, pFmt->cbSize);
- pFmt->dwMask &= PFM_ALL;
- }
- pFmt->cbSize = cbSize;
+ UINT size = fmt->cbSize;
+
+ if (fmt->cbSize >= sizeof(PARAFORMAT2))
+ *fmt = para->fmt;
+ else
+ {
+ memcpy( fmt, ¶->fmt, fmt->cbSize );
+ fmt->dwMask &= PFM_ALL;
+ }
+ fmt->cbSize = size;
}
-void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt)
+void editor_get_selection_para_fmt( ME_TextEditor *editor, PARAFORMAT2 *fmt )
{
- ME_DisplayItem *para, *para_end;
- PARAFORMAT2 *curFmt;
+ ME_Paragraph *para, *para_end;
- if (pFmt->cbSize < sizeof(PARAFORMAT))
+ if (fmt->cbSize < sizeof(PARAFORMAT))
{
- pFmt->dwMask = 0;
+ fmt->dwMask = 0;
return;
}
- ME_GetSelectionParas(editor, ¶, ¶_end);
+ editor_get_selection_paras( editor, ¶, ¶_end );
- ME_GetParaFormat(editor, para, pFmt);
+ para_copy_fmt( para, fmt );
/* Invalidate values that change across the selected paragraphs. */
while (para != para_end)
{
- para = para->member.para.next_para;
- curFmt = ¶->member.para.fmt;
+ para = para_next( para );
#define CHECK_FIELD(m, f) \
- if (pFmt->f != curFmt->f) pFmt->dwMask &= ~(m);
+ if (fmt->f != para->fmt.f) fmt->dwMask &= ~(m);
CHECK_FIELD(PFM_NUMBERING, wNumbering);
CHECK_FIELD(PFM_STARTINDENT, dxStartIndent);
CHECK_FIELD(PFM_RIGHTINDENT, dxRightIndent);
CHECK_FIELD(PFM_OFFSET, dxOffset);
CHECK_FIELD(PFM_ALIGNMENT, wAlignment);
- if (pFmt->dwMask & PFM_TABSTOPS)
+ if (fmt->dwMask & PFM_TABSTOPS)
{
- if (pFmt->cTabCount != para->member.para.fmt.cTabCount ||
- memcmp(pFmt->rgxTabs, curFmt->rgxTabs, curFmt->cTabCount*sizeof(int)))
- pFmt->dwMask &= ~PFM_TABSTOPS;
+ if (fmt->cTabCount != para->fmt.cTabCount ||
+ memcmp(fmt->rgxTabs, para->fmt.rgxTabs, para->fmt.cTabCount * sizeof(int) ))
+ fmt->dwMask &= ~PFM_TABSTOPS;
}
- if (pFmt->cbSize >= sizeof(PARAFORMAT2))
+ if (fmt->cbSize >= sizeof(PARAFORMAT2))
{
- pFmt->dwMask &= ~((pFmt->wEffects ^ curFmt->wEffects) << 16);
+ fmt->dwMask &= ~((fmt->wEffects ^ para->fmt.wEffects) << 16);
CHECK_FIELD(PFM_SPACEBEFORE, dySpaceBefore);
CHECK_FIELD(PFM_SPACEAFTER, dySpaceAfter);
CHECK_FIELD(PFM_LINESPACING, dyLineSpacing);
@@ -980,7 +978,7 @@ void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt)
}
}
-void ME_SetDefaultParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt)
+void editor_set_default_para_fmt( ME_TextEditor *editor, PARAFORMAT2 *pFmt )
{
const PARAFORMAT2 *host_fmt;
HRESULT hr;
diff --git a/dlls/riched20/reader.c b/dlls/riched20/reader.c
index dc551bf5841..e73b8b87e9d 100644
--- a/dlls/riched20/reader.c
+++ b/dlls/riched20/reader.c
@@ -2519,7 +2519,7 @@ static void SpecialChar (RTF_Info *info)
case rtfSect:
case rtfPar:
RTFFlushOutputBuffer(info);
- ME_SetSelectionParaFormat(info->editor, &info->fmt);
+ editor_set_selection_para_fmt( info->editor, &info->fmt );
memset(&info->fmt, 0, sizeof(info->fmt));
info->fmt.cbSize = sizeof(info->fmt);
RTFPutUnicodeChar (info, '\r');
--
2.23.0
1
0
Mostly to test that when doing mode restoration, all display outputs get restored to their display
settings in the registry, not just one output gets restored.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/ddraw/tests/ddraw1.c | 396 ++++++++++++++++++++++++++++++++++++-
dlls/ddraw/tests/ddraw2.c | 397 +++++++++++++++++++++++++++++++++++++-
dlls/ddraw/tests/ddraw4.c | 396 ++++++++++++++++++++++++++++++++++++-
dlls/ddraw/tests/ddraw7.c | 396 ++++++++++++++++++++++++++++++++++++-
4 files changed, 1581 insertions(+), 4 deletions(-)
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index 63791c5b606..783c1b961a0 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -265,6 +265,69 @@ static IDirectDrawSurface *get_depth_stencil(IDirect3DDevice *device)
return ret;
}
+/* Free original_modes after finished using it */
+static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
+{
+ unsigned int number, size = 2, count = 0, index = 0;
+ DISPLAY_DEVICEW display_device;
+ DEVMODEW *modes, *tmp;
+
+ if (!(modes = heap_alloc(size * sizeof(*modes))))
+ return FALSE;
+
+ display_device.cb = sizeof(display_device);
+ while (EnumDisplayDevicesW(NULL, index++, &display_device, 0))
+ {
+ /* Skip software devices */
+ if (swscanf(display_device.DeviceName, L"\\\\.\\DISPLAY%u", &number) != 1)
+ continue;
+
+ if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
+ continue;
+
+ if (count >= size)
+ {
+ size *= 2;
+ if (!(tmp = heap_realloc(modes, size * sizeof(*modes))))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+ modes = tmp;
+ }
+
+ memset(&modes[count], 0, sizeof(modes[count]));
+ modes[count].dmSize = sizeof(modes[count]);
+ if (!EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &modes[count]))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+
+ lstrcpyW(modes[count++].dmDeviceName, display_device.DeviceName);
+ }
+
+ *original_modes = modes;
+ *display_count = count;
+ return TRUE;
+}
+
+static BOOL restore_display_modes(DEVMODEW *modes, unsigned int count)
+{
+ unsigned int index;
+ LONG ret;
+
+ for (index = 0; index < count; ++index)
+ {
+ ret = ChangeDisplaySettingsExW(modes[index].dmDeviceName, &modes[index], NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ if (ret != DISP_CHANGE_SUCCESSFUL)
+ return FALSE;
+ }
+ ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
+ return ret == DISP_CHANGE_SUCCESSFUL;
+}
+
static HRESULT set_display_mode(IDirectDraw *ddraw, DWORD width, DWORD height)
{
if (SUCCEEDED(IDirectDraw_SetDisplayMode(ddraw, width, height, 32)))
@@ -1301,6 +1364,14 @@ static void test_coop_level_threaded(void)
IDirectDraw_Release(ddraw);
}
+static BOOL compare_mode_rect(const DEVMODEW *mode1, const DEVMODEW *mode2)
+{
+ return mode1->dmPosition.x == mode2->dmPosition.x
+ && mode1->dmPosition.y == mode2->dmPosition.y
+ && mode1->dmPelsWidth == mode2->dmPelsWidth
+ && mode1->dmPelsHeight == mode2->dmPelsHeight;
+}
+
static ULONG get_refcount(IUnknown *test_iface)
{
IUnknown_AddRef(test_iface);
@@ -2630,6 +2701,8 @@ static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC *surface_
static void test_coop_level_mode_set(void)
{
+ DEVMODEW *original_modes = NULL, devmode, devmode2;
+ unsigned int display_count = 0;
IDirectDrawSurface *primary;
RECT registry_rect, ddraw_rect, user32_rect, r;
IDirectDraw *ddraw;
@@ -2640,7 +2713,6 @@ static void test_coop_level_mode_set(void)
ULONG ref;
MSG msg;
struct test_coop_level_mode_set_enum_param param;
- DEVMODEW devmode;
BOOL ret;
LONG change_ret;
@@ -2716,6 +2788,18 @@ static void test_coop_level_mode_set(void)
{0, FALSE, 0},
};
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
+
ddraw = create_ddraw();
ok(!!ddraw, "Failed to create a ddraw object.\n");
@@ -2728,6 +2812,7 @@ static void test_coop_level_mode_set(void)
if (!param.user32_height)
{
skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
+ heap_free(original_modes);
return;
}
@@ -3315,19 +3400,125 @@ static void test_coop_level_mode_set(void)
ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
wine_dbgstr_rect(&r));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that no mode restorations if no mode changes happened */
+ devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
+ devmode.dmPelsWidth = param.user32_width;
+ devmode.dmPelsHeight = param.user32_height;
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ ref = IDirectDraw_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ memset(&devmode2, 0, sizeof(devmode2));
+ devmode2.dmSize = sizeof(devmode2);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, ®istry_mode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that no mode restorations if no mode changes happened with fullscreen ddraw objects */
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ ref = IDirectDraw_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, ®istry_mode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry after ddraw object releases
+ * if SetDisplayMode() was called */
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry after RestoreDisplayMode() */
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw_RestoreDisplayMode(ddraw);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
done:
expect_messages = NULL;
DestroyWindow(window);
UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_coop_level_mode_set_multi(void)
{
+ DEVMODEW old_devmode, devmode, devmode2, devmode3, *original_modes = NULL;
+ unsigned int mode_idx = 0, display_idx, display_count = 0;
+ WCHAR second_monitor_name[CCHDEVICENAME];
IDirectDraw *ddraw1, *ddraw2;
+ LONG change_ret;
UINT w, h;
HWND window;
HRESULT hr;
ULONG ref;
+ BOOL ret;
+
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
0, 0, 100, 100, 0, 0, 0, 0);
@@ -3509,7 +3700,210 @@ static void test_coop_level_mode_set_multi(void)
h = GetSystemMetrics(SM_CYSCREEN);
ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
+ if (display_count < 2)
+ {
+ skip("Following tests require two monitors.\n");
+ goto done;
+ }
+
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ second_monitor_name[0] = '\0';
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (original_modes[display_idx].dmPosition.x || original_modes[display_idx].dmPosition.y)
+ {
+ lstrcpyW(second_monitor_name, original_modes[display_idx].dmDeviceName);
+ break;
+ }
+ }
+ ok(lstrlenW(second_monitor_name), "Got an empty second monitor name.\n");
+ memset(&old_devmode, 0, sizeof(old_devmode));
+ old_devmode.dmSize = sizeof(old_devmode);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &old_devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+
+ devmode = old_devmode;
+ while (EnumDisplaySettingsW(second_monitor_name, mode_idx++, &devmode))
+ {
+ if (devmode.dmPelsWidth != old_devmode.dmPelsWidth
+ || devmode.dmPelsHeight != old_devmode.dmPelsHeight)
+ break;
+ }
+ ok(devmode.dmPelsWidth != old_devmode.dmPelsWidth
+ || devmode.dmPelsHeight != old_devmode.dmPelsHeight,
+ "Failed to find a different mode for the second monitor.\n");
+
+ /* Test that no mode restorations for non-primary monitors if SetDisplayMode() was not called */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = IDirectDraw_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ memset(&devmode2, 0, sizeof(devmode2));
+ devmode2.dmSize = sizeof(devmode2);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ if (compare_mode_rect(&devmode2, &old_devmode))
+ {
+ skip("Failed to change display settings of the second monitor.\n");
+ ref = IDirectDraw_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ goto done;
+ }
+
+ hr = IDirectDraw_SetCooperativeLevel(ddraw1, window, DDSCL_NORMAL);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ ref = IDirectDraw_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ memset(&devmode3, 0, sizeof(devmode3));
+ devmode3.dmSize = sizeof(devmode3);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode3);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode3, &devmode2), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations happen for non-primary monitors on ddraw releases if
+ * SetDisplayMode() was called */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations happen for non-primary monitors as well */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw_RestoreDisplayMode(ddraw1);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations for non-primary monitors use display settings in the registry */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
+ * objects and one of them restores display mode */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ ddraw2 = create_ddraw();
+ ok(!!ddraw2, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+ hr = set_display_mode(ddraw2, 640, 480);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw_RestoreDisplayMode(ddraw2);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw_Release(ddraw2);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ref = IDirectDraw_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
+ * objects and one of them got released */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ ddraw2 = create_ddraw();
+ ok(!!ddraw2, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+ hr = set_display_mode(ddraw2, 640, 480);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw_Release(ddraw2);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+done:
DestroyWindow(window);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_initialize(void)
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index 4b83230de1f..23d3e0c1f02 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -22,6 +22,7 @@
#define COBJMACROS
#include "wine/test.h"
+#include "wine/heap.h"
#include <limits.h>
#include <math.h>
#include "ddrawi.h"
@@ -261,6 +262,69 @@ static IDirectDrawSurface *get_depth_stencil(IDirect3DDevice2 *device)
return ret;
}
+/* Free original_modes after finished using it */
+static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
+{
+ unsigned int number, size = 2, count = 0, index = 0;
+ DISPLAY_DEVICEW display_device;
+ DEVMODEW *modes, *tmp;
+
+ if (!(modes = heap_alloc(size * sizeof(*modes))))
+ return FALSE;
+
+ display_device.cb = sizeof(display_device);
+ while (EnumDisplayDevicesW(NULL, index++, &display_device, 0))
+ {
+ /* Skip software devices */
+ if (swscanf(display_device.DeviceName, L"\\\\.\\DISPLAY%u", &number) != 1)
+ continue;
+
+ if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
+ continue;
+
+ if (count >= size)
+ {
+ size *= 2;
+ if (!(tmp = heap_realloc(modes, size * sizeof(*modes))))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+ modes = tmp;
+ }
+
+ memset(&modes[count], 0, sizeof(modes[count]));
+ modes[count].dmSize = sizeof(modes[count]);
+ if (!EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &modes[count]))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+
+ lstrcpyW(modes[count++].dmDeviceName, display_device.DeviceName);
+ }
+
+ *original_modes = modes;
+ *display_count = count;
+ return TRUE;
+}
+
+static BOOL restore_display_modes(DEVMODEW *modes, unsigned int count)
+{
+ unsigned int index;
+ LONG ret;
+
+ for (index = 0; index < count; ++index)
+ {
+ ret = ChangeDisplaySettingsExW(modes[index].dmDeviceName, &modes[index], NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ if (ret != DISP_CHANGE_SUCCESSFUL)
+ return FALSE;
+ }
+ ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
+ return ret == DISP_CHANGE_SUCCESSFUL;
+}
+
static HRESULT set_display_mode(IDirectDraw2 *ddraw, DWORD width, DWORD height)
{
if (SUCCEEDED(IDirectDraw2_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
@@ -1458,6 +1522,14 @@ done:
if (ddraw) IDirectDraw2_Release(ddraw);
}
+static BOOL compare_mode_rect(const DEVMODEW *mode1, const DEVMODEW *mode2)
+{
+ return mode1->dmPosition.x == mode2->dmPosition.x
+ && mode1->dmPosition.y == mode2->dmPosition.y
+ && mode1->dmPelsWidth == mode2->dmPelsWidth
+ && mode1->dmPelsHeight == mode2->dmPelsHeight;
+}
+
static ULONG get_refcount(IUnknown *test_iface)
{
IUnknown_AddRef(test_iface);
@@ -2694,6 +2766,8 @@ static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC *surface_
static void test_coop_level_mode_set(void)
{
+ DEVMODEW *original_modes = NULL, devmode, devmode2;
+ unsigned int display_count = 0;
IDirectDrawSurface *primary;
RECT registry_rect, ddraw_rect, user32_rect, r;
IDirectDraw2 *ddraw;
@@ -2704,7 +2778,6 @@ static void test_coop_level_mode_set(void)
ULONG ref;
MSG msg;
struct test_coop_level_mode_set_enum_param param;
- DEVMODEW devmode;
BOOL ret;
LONG change_ret;
@@ -2780,6 +2853,18 @@ static void test_coop_level_mode_set(void)
{0, FALSE, 0},
};
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
+
ddraw = create_ddraw();
ok(!!ddraw, "Failed to create a ddraw object.\n");
@@ -2792,6 +2877,7 @@ static void test_coop_level_mode_set(void)
if (!param.user32_height)
{
skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
+ heap_free(original_modes);
return;
}
@@ -3472,21 +3558,127 @@ static void test_coop_level_mode_set(void)
ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
wine_dbgstr_rect(&r));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that no mode restorations if no mode changes happened */
+ devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
+ devmode.dmPelsWidth = param.user32_width;
+ devmode.dmPelsHeight = param.user32_height;
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ ref = IDirectDraw2_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ memset(&devmode2, 0, sizeof(devmode2));
+ devmode2.dmSize = sizeof(devmode2);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, ®istry_mode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that no mode restorations if no mode changes happened with fullscreen ddraw objects */
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ ref = IDirectDraw2_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, ®istry_mode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry after ddraw object releases
+ * if SetDisplayMode() was called */
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw2_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry after RestoreDisplayMode() */
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw2_RestoreDisplayMode(ddraw);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw2_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
done:
expect_messages = NULL;
DestroyWindow(window);
DestroyWindow(window2);
UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_coop_level_mode_set_multi(void)
{
+ DEVMODEW old_devmode, devmode, devmode2, devmode3, *original_modes = NULL;
+ unsigned int mode_idx = 0, display_idx, display_count = 0;
+ WCHAR second_monitor_name[CCHDEVICENAME];
IDirectDraw2 *ddraw1, *ddraw2;
+ LONG change_ret;
UINT w, h;
HWND window;
HRESULT hr;
ULONG ref;
+ BOOL ret;
+
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
0, 0, 100, 100, 0, 0, 0, 0);
@@ -3668,7 +3860,210 @@ static void test_coop_level_mode_set_multi(void)
h = GetSystemMetrics(SM_CYSCREEN);
ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
+ if (display_count < 2)
+ {
+ skip("Following tests require two monitors.\n");
+ goto done;
+ }
+
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ second_monitor_name[0] = '\0';
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (original_modes[display_idx].dmPosition.x || original_modes[display_idx].dmPosition.y)
+ {
+ lstrcpyW(second_monitor_name, original_modes[display_idx].dmDeviceName);
+ break;
+ }
+ }
+ ok(lstrlenW(second_monitor_name), "Got an empty second monitor name.\n");
+ memset(&old_devmode, 0, sizeof(old_devmode));
+ old_devmode.dmSize = sizeof(old_devmode);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &old_devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+
+ devmode = old_devmode;
+ while (EnumDisplaySettingsW(second_monitor_name, mode_idx++, &devmode))
+ {
+ if (devmode.dmPelsWidth != old_devmode.dmPelsWidth
+ || devmode.dmPelsHeight != old_devmode.dmPelsHeight)
+ break;
+ }
+ ok(devmode.dmPelsWidth != old_devmode.dmPelsWidth
+ || devmode.dmPelsHeight != old_devmode.dmPelsHeight,
+ "Failed to find a different mode for the second monitor.\n");
+
+ /* Test that no mode restorations for non-primary monitors if SetDisplayMode() was not called */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = IDirectDraw2_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ memset(&devmode2, 0, sizeof(devmode2));
+ devmode2.dmSize = sizeof(devmode2);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ if (compare_mode_rect(&devmode2, &old_devmode))
+ {
+ skip("Failed to change display settings of the second monitor.\n");
+ ref = IDirectDraw2_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ goto done;
+ }
+
+ hr = IDirectDraw2_SetCooperativeLevel(ddraw1, window, DDSCL_NORMAL);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ ref = IDirectDraw2_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ memset(&devmode3, 0, sizeof(devmode3));
+ devmode3.dmSize = sizeof(devmode3);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode3);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode3, &devmode2), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations happen for non-primary monitors on ddraw releases if
+ * SetDisplayMode() was called */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw2_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations happen for non-primary monitors as well */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw2_RestoreDisplayMode(ddraw1);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw2_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations for non-primary monitors use display settings in the registry */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw2_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
+ * objects and one of them restores display mode */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ ddraw2 = create_ddraw();
+ ok(!!ddraw2, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+ hr = set_display_mode(ddraw2, 640, 480);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw2_RestoreDisplayMode(ddraw2);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw2_Release(ddraw2);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ref = IDirectDraw2_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
+ * objects and one of them got released */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ ddraw2 = create_ddraw();
+ ok(!!ddraw2, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+ hr = set_display_mode(ddraw2, 640, 480);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw2_Release(ddraw2);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw2_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+done:
DestroyWindow(window);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_initialize(void)
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index 72aad35b1e1..12cfbc3784f 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -263,6 +263,69 @@ static IDirectDrawSurface4 *get_depth_stencil(IDirect3DDevice3 *device)
return ret;
}
+/* Free original_modes after finished using it */
+static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
+{
+ unsigned int number, size = 2, count = 0, index = 0;
+ DISPLAY_DEVICEW display_device;
+ DEVMODEW *modes, *tmp;
+
+ if (!(modes = heap_alloc(size * sizeof(*modes))))
+ return FALSE;
+
+ display_device.cb = sizeof(display_device);
+ while (EnumDisplayDevicesW(NULL, index++, &display_device, 0))
+ {
+ /* Skip software devices */
+ if (swscanf(display_device.DeviceName, L"\\\\.\\DISPLAY%u", &number) != 1)
+ continue;
+
+ if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
+ continue;
+
+ if (count >= size)
+ {
+ size *= 2;
+ if (!(tmp = heap_realloc(modes, size * sizeof(*modes))))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+ modes = tmp;
+ }
+
+ memset(&modes[count], 0, sizeof(modes[count]));
+ modes[count].dmSize = sizeof(modes[count]);
+ if (!EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &modes[count]))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+
+ lstrcpyW(modes[count++].dmDeviceName, display_device.DeviceName);
+ }
+
+ *original_modes = modes;
+ *display_count = count;
+ return TRUE;
+}
+
+static BOOL restore_display_modes(DEVMODEW *modes, unsigned int count)
+{
+ unsigned int index;
+ LONG ret;
+
+ for (index = 0; index < count; ++index)
+ {
+ ret = ChangeDisplaySettingsExW(modes[index].dmDeviceName, &modes[index], NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ if (ret != DISP_CHANGE_SUCCESSFUL)
+ return FALSE;
+ }
+ ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
+ return ret == DISP_CHANGE_SUCCESSFUL;
+}
+
static HRESULT set_display_mode(IDirectDraw4 *ddraw, DWORD width, DWORD height)
{
if (SUCCEEDED(IDirectDraw4_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
@@ -1628,6 +1691,14 @@ static void test_texture_load_ckey(void)
IDirectDraw4_Release(ddraw);
}
+static BOOL compare_mode_rect(const DEVMODEW *mode1, const DEVMODEW *mode2)
+{
+ return mode1->dmPosition.x == mode2->dmPosition.x
+ && mode1->dmPosition.y == mode2->dmPosition.y
+ && mode1->dmPelsWidth == mode2->dmPelsWidth
+ && mode1->dmPelsHeight == mode2->dmPelsHeight;
+}
+
static ULONG get_refcount(IUnknown *test_iface)
{
IUnknown_AddRef(test_iface);
@@ -2935,6 +3006,8 @@ static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC2 *surface
static void test_coop_level_mode_set(void)
{
+ DEVMODEW *original_modes = NULL, devmode, devmode2;
+ unsigned int display_count = 0;
IDirectDrawSurface4 *primary;
RECT registry_rect, ddraw_rect, user32_rect, r;
IDirectDraw4 *ddraw;
@@ -2945,7 +3018,6 @@ static void test_coop_level_mode_set(void)
ULONG ref;
MSG msg;
struct test_coop_level_mode_set_enum_param param;
- DEVMODEW devmode;
BOOL ret;
LONG change_ret;
@@ -3021,6 +3093,18 @@ static void test_coop_level_mode_set(void)
{0, FALSE, 0},
};
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
+
ddraw = create_ddraw();
ok(!!ddraw, "Failed to create a ddraw object.\n");
@@ -3033,6 +3117,7 @@ static void test_coop_level_mode_set(void)
if (!param.user32_height)
{
skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
+ heap_free(original_modes);
return;
}
@@ -3709,20 +3794,126 @@ static void test_coop_level_mode_set(void)
ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
wine_dbgstr_rect(&r));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that no mode restorations if no mode changes happened */
+ devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
+ devmode.dmPelsWidth = param.user32_width;
+ devmode.dmPelsHeight = param.user32_height;
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ ref = IDirectDraw4_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ memset(&devmode2, 0, sizeof(devmode2));
+ devmode2.dmSize = sizeof(devmode2);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, ®istry_mode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that no mode restorations if no mode changes happened with fullscreen ddraw objects */
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ ref = IDirectDraw4_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, ®istry_mode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry after ddraw object releases
+ * if SetDisplayMode() was called */
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw4_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry after RestoreDisplayMode() */
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw4_RestoreDisplayMode(ddraw);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw4_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
expect_messages = NULL;
DestroyWindow(window);
DestroyWindow(window2);
UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_coop_level_mode_set_multi(void)
{
+ DEVMODEW old_devmode, devmode, devmode2, devmode3, *original_modes = NULL;
+ unsigned int mode_idx = 0, display_idx, display_count = 0;
+ WCHAR second_monitor_name[CCHDEVICENAME];
IDirectDraw4 *ddraw1, *ddraw2;
+ LONG change_ret;
UINT w, h;
HWND window;
HRESULT hr;
ULONG ref;
+ BOOL ret;
+
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
0, 0, 100, 100, 0, 0, 0, 0);
@@ -3897,7 +4088,210 @@ static void test_coop_level_mode_set_multi(void)
h = GetSystemMetrics(SM_CYSCREEN);
ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
+ if (display_count < 2)
+ {
+ skip("Following tests require two monitors.\n");
+ goto done;
+ }
+
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ second_monitor_name[0] = '\0';
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (original_modes[display_idx].dmPosition.x || original_modes[display_idx].dmPosition.y)
+ {
+ lstrcpyW(second_monitor_name, original_modes[display_idx].dmDeviceName);
+ break;
+ }
+ }
+ ok(lstrlenW(second_monitor_name), "Got an empty second monitor name.\n");
+ memset(&old_devmode, 0, sizeof(old_devmode));
+ old_devmode.dmSize = sizeof(old_devmode);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &old_devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+
+ devmode = old_devmode;
+ while (EnumDisplaySettingsW(second_monitor_name, mode_idx++, &devmode))
+ {
+ if (devmode.dmPelsWidth != old_devmode.dmPelsWidth
+ || devmode.dmPelsHeight != old_devmode.dmPelsHeight)
+ break;
+ }
+ ok(devmode.dmPelsWidth != old_devmode.dmPelsWidth
+ || devmode.dmPelsHeight != old_devmode.dmPelsHeight,
+ "Failed to find a different mode for the second monitor.\n");
+
+ /* Test that no mode restorations for non-primary monitors if SetDisplayMode() was not called */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = IDirectDraw4_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ memset(&devmode2, 0, sizeof(devmode2));
+ devmode2.dmSize = sizeof(devmode2);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ if (compare_mode_rect(&devmode2, &old_devmode))
+ {
+ skip("Failed to change display settings of the second monitor.\n");
+ ref = IDirectDraw4_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ goto done;
+ }
+
+ hr = IDirectDraw4_SetCooperativeLevel(ddraw1, window, DDSCL_NORMAL);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ ref = IDirectDraw4_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ memset(&devmode3, 0, sizeof(devmode3));
+ devmode3.dmSize = sizeof(devmode3);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode3);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode3, &devmode2), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations happen for non-primary monitors on ddraw releases if
+ * SetDisplayMode() was called */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw4_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations happen for non-primary monitors as well */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw4_RestoreDisplayMode(ddraw1);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw4_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations for non-primary monitors use display settings in the registry */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw4_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
+ * objects and one of them restores display mode */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ ddraw2 = create_ddraw();
+ ok(!!ddraw2, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+ hr = set_display_mode(ddraw2, 640, 480);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw4_RestoreDisplayMode(ddraw2);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw4_Release(ddraw2);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ref = IDirectDraw4_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
+ * objects and one of them got released */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ ddraw2 = create_ddraw();
+ ok(!!ddraw2, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+ hr = set_display_mode(ddraw2, 640, 480);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw4_Release(ddraw2);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw4_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+done:
DestroyWindow(window);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_initialize(void)
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index e85b7d76369..c214cbc221e 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -102,6 +102,14 @@ static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
&& compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff);
}
+static BOOL compare_mode_rect(const DEVMODEW *mode1, const DEVMODEW *mode2)
+{
+ return mode1->dmPosition.x == mode2->dmPosition.x
+ && mode1->dmPosition.y == mode2->dmPosition.y
+ && mode1->dmPelsWidth == mode2->dmPelsWidth
+ && mode1->dmPelsHeight == mode2->dmPelsHeight;
+}
+
static ULONG get_refcount(IUnknown *iface)
{
IUnknown_AddRef(iface);
@@ -281,6 +289,69 @@ static IDirectDrawSurface7 *get_depth_stencil(IDirect3DDevice7 *device)
return ret;
}
+/* Free original_modes after finished using it */
+static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
+{
+ unsigned int number, size = 2, count = 0, index = 0;
+ DISPLAY_DEVICEW display_device;
+ DEVMODEW *modes, *tmp;
+
+ if (!(modes = heap_alloc(size * sizeof(*modes))))
+ return FALSE;
+
+ display_device.cb = sizeof(display_device);
+ while (EnumDisplayDevicesW(NULL, index++, &display_device, 0))
+ {
+ /* Skip software devices */
+ if (swscanf(display_device.DeviceName, L"\\\\.\\DISPLAY%u", &number) != 1)
+ continue;
+
+ if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
+ continue;
+
+ if (count >= size)
+ {
+ size *= 2;
+ if (!(tmp = heap_realloc(modes, size * sizeof(*modes))))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+ modes = tmp;
+ }
+
+ memset(&modes[count], 0, sizeof(modes[count]));
+ modes[count].dmSize = sizeof(modes[count]);
+ if (!EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &modes[count]))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+
+ lstrcpyW(modes[count++].dmDeviceName, display_device.DeviceName);
+ }
+
+ *original_modes = modes;
+ *display_count = count;
+ return TRUE;
+}
+
+static BOOL restore_display_modes(DEVMODEW *modes, unsigned int count)
+{
+ unsigned int index;
+ LONG ret;
+
+ for (index = 0; index < count; ++index)
+ {
+ ret = ChangeDisplaySettingsExW(modes[index].dmDeviceName, &modes[index], NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ if (ret != DISP_CHANGE_SUCCESSFUL)
+ return FALSE;
+ }
+ ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
+ return ret == DISP_CHANGE_SUCCESSFUL;
+}
+
static HRESULT set_display_mode(IDirectDraw7 *ddraw, DWORD width, DWORD height)
{
if (SUCCEEDED(IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, 0, 0)))
@@ -2582,6 +2653,8 @@ static HRESULT CALLBACK test_coop_level_mode_set_enum_cb(DDSURFACEDESC2 *surface
static void test_coop_level_mode_set(void)
{
+ DEVMODEW *original_modes = NULL, devmode, devmode2;
+ unsigned int display_count = 0;
IDirectDrawSurface7 *primary;
RECT registry_rect, ddraw_rect, user32_rect, r;
IDirectDraw7 *ddraw;
@@ -2592,7 +2665,6 @@ static void test_coop_level_mode_set(void)
ULONG ref;
MSG msg;
struct test_coop_level_mode_set_enum_param param;
- DEVMODEW devmode;
BOOL ret;
LONG change_ret;
@@ -2668,6 +2740,18 @@ static void test_coop_level_mode_set(void)
{0, FALSE, 0},
};
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
+
ddraw = create_ddraw();
ok(!!ddraw, "Failed to create a ddraw object.\n");
@@ -2680,6 +2764,7 @@ static void test_coop_level_mode_set(void)
if (!param.user32_height)
{
skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
+ heap_free(original_modes);
return;
}
@@ -3356,20 +3441,126 @@ static void test_coop_level_mode_set(void)
ok(EqualRect(&r, &ddraw_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&ddraw_rect),
wine_dbgstr_rect(&r));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that no mode restorations if no mode changes happened */
+ devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
+ devmode.dmPelsWidth = param.user32_width;
+ devmode.dmPelsHeight = param.user32_height;
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ ref = IDirectDraw7_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ memset(&devmode2, 0, sizeof(devmode2));
+ devmode2.dmSize = sizeof(devmode2);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, ®istry_mode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that no mode restorations if no mode changes happened with fullscreen ddraw objects */
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ ref = IDirectDraw7_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, ®istry_mode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry after ddraw object releases
+ * if SetDisplayMode() was called */
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw7_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry after RestoreDisplayMode() */
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw7_RestoreDisplayMode(ddraw);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw7_Release(ddraw);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
expect_messages = NULL;
DestroyWindow(window);
DestroyWindow(window2);
UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
UnregisterClassA("ddraw_test_wndproc_wc2", GetModuleHandleA(NULL));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_coop_level_mode_set_multi(void)
{
+ DEVMODEW old_devmode, devmode, devmode2, devmode3, *original_modes = NULL;
+ unsigned int mode_idx = 0, display_idx, display_count = 0;
+ WCHAR second_monitor_name[CCHDEVICENAME];
IDirectDraw7 *ddraw1, *ddraw2;
+ LONG change_ret;
UINT w, h;
HWND window;
HRESULT hr;
ULONG ref;
+ BOOL ret;
+
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
0, 0, 100, 100, 0, 0, 0, 0);
@@ -3544,7 +3735,210 @@ static void test_coop_level_mode_set_multi(void)
h = GetSystemMetrics(SM_CYSCREEN);
ok(h == registry_mode.dmPelsHeight, "Got unexpected screen height %u.\n", h);
+ if (display_count < 2)
+ {
+ skip("Following tests require two monitors.\n");
+ goto done;
+ }
+
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ second_monitor_name[0] = '\0';
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (original_modes[display_idx].dmPosition.x || original_modes[display_idx].dmPosition.y)
+ {
+ lstrcpyW(second_monitor_name, original_modes[display_idx].dmDeviceName);
+ break;
+ }
+ }
+ ok(lstrlenW(second_monitor_name), "Got an empty second monitor name.\n");
+ memset(&old_devmode, 0, sizeof(old_devmode));
+ old_devmode.dmSize = sizeof(old_devmode);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &old_devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+
+ devmode = old_devmode;
+ while (EnumDisplaySettingsW(second_monitor_name, mode_idx++, &devmode))
+ {
+ if (devmode.dmPelsWidth != old_devmode.dmPelsWidth
+ || devmode.dmPelsHeight != old_devmode.dmPelsHeight)
+ break;
+ }
+ ok(devmode.dmPelsWidth != old_devmode.dmPelsWidth
+ || devmode.dmPelsHeight != old_devmode.dmPelsHeight,
+ "Failed to find a different mode for the second monitor.\n");
+
+ /* Test that no mode restorations for non-primary monitors if SetDisplayMode() was not called */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = IDirectDraw7_SetCooperativeLevel(ddraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ memset(&devmode2, 0, sizeof(devmode2));
+ devmode2.dmSize = sizeof(devmode2);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ if (compare_mode_rect(&devmode2, &old_devmode))
+ {
+ skip("Failed to change display settings of the second monitor.\n");
+ ref = IDirectDraw7_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ goto done;
+ }
+
+ hr = IDirectDraw7_SetCooperativeLevel(ddraw1, window, DDSCL_NORMAL);
+ ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
+ ref = IDirectDraw7_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ memset(&devmode3, 0, sizeof(devmode3));
+ devmode3.dmSize = sizeof(devmode3);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode3);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode3, &devmode2), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations happen for non-primary monitors on ddraw releases if
+ * SetDisplayMode() was called */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw7_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations happen for non-primary monitors as well */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw7_RestoreDisplayMode(ddraw1);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw7_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations for non-primary monitors use display settings in the registry */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw7_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
+ * objects and one of them restores display mode */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ ddraw2 = create_ddraw();
+ ok(!!ddraw2, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+ hr = set_display_mode(ddraw2, 640, 480);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ hr = IDirectDraw7_RestoreDisplayMode(ddraw2);
+ ok(hr == DD_OK, "RestoreDisplayMode failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw7_Release(ddraw2);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ref = IDirectDraw7_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test mode restorations for non-primary monitors when there are multiple fullscreen ddraw
+ * objects and one of them got released */
+ ddraw1 = create_ddraw();
+ ok(!!ddraw1, "Failed to create a ddraw object.\n");
+ ddraw2 = create_ddraw();
+ ok(!!ddraw2, "Failed to create a ddraw object.\n");
+ hr = set_display_mode(ddraw1, 800, 600);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+ hr = set_display_mode(ddraw2, 640, 480);
+ ok(hr == DD_OK, "Failed to set display mode, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ ref = IDirectDraw7_Release(ddraw2);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(compare_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+
+ ref = IDirectDraw7_Release(ddraw1);
+ ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
+
+done:
DestroyWindow(window);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_initialize(void)
--
2.27.0
2
1
[PATCH 1/8] d3d8/tests: Restore display modes at the end of test_wndproc().
by Zhiyi Zhang Oct. 28, 2020
by Zhiyi Zhang Oct. 28, 2020
Oct. 28, 2020
test_wndproc() makes a series of ChangeDisplaySettings() calls that could make the current display
mode no longer match the registry display mode. Restore display modes at the end of test_wndproc()
so that other tests are not affected.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/d3d8/tests/device.c | 72 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 71 insertions(+), 1 deletion(-)
diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c
index 4c567a47603..f48a51cee85 100644
--- a/dlls/d3d8/tests/device.c
+++ b/dlls/d3d8/tests/device.c
@@ -114,6 +114,69 @@ static BOOL adapter_is_warp(const D3DADAPTER_IDENTIFIER8 *identifier)
return !strcmp(identifier->Driver, "d3d10warp.dll");
}
+/* Free original_modes after finished using it */
+static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
+{
+ unsigned int number, size = 2, count = 0, index = 0;
+ DISPLAY_DEVICEW display_device;
+ DEVMODEW *modes, *tmp;
+
+ if (!(modes = heap_alloc(size * sizeof(*modes))))
+ return FALSE;
+
+ display_device.cb = sizeof(display_device);
+ while (EnumDisplayDevicesW(NULL, index++, &display_device, 0))
+ {
+ /* Skip software devices */
+ if (swscanf(display_device.DeviceName, L"\\\\.\\DISPLAY%u", &number) != 1)
+ continue;
+
+ if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
+ continue;
+
+ if (count >= size)
+ {
+ size *= 2;
+ if (!(tmp = heap_realloc(modes, size * sizeof(*modes))))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+ modes = tmp;
+ }
+
+ memset(&modes[count], 0, sizeof(modes[count]));
+ modes[count].dmSize = sizeof(modes[count]);
+ if (!EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &modes[count]))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+
+ lstrcpyW(modes[count++].dmDeviceName, display_device.DeviceName);
+ }
+
+ *original_modes = modes;
+ *display_count = count;
+ return TRUE;
+}
+
+static BOOL restore_display_modes(DEVMODEW *modes, unsigned int count)
+{
+ unsigned int index;
+ LONG ret;
+
+ for (index = 0; index < count; ++index)
+ {
+ ret = ChangeDisplaySettingsExW(modes[index].dmDeviceName, &modes[index], NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ if (ret != DISP_CHANGE_SUCCESSFUL)
+ return FALSE;
+ }
+ ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
+ return ret == DISP_CHANGE_SUCCESSFUL;
+}
+
static IDirect3DDevice8 *create_device(IDirect3D8 *d3d8, HWND focus_window, const struct device_desc *desc)
{
D3DPRESENT_PARAMETERS present_parameters = {0};
@@ -2763,6 +2826,8 @@ static DWORD WINAPI wndproc_thread(void *param)
static void test_wndproc(void)
{
struct wndproc_thread_param thread_params;
+ DEVMODEW devmode, *original_modes = NULL;
+ unsigned int display_count = 0;
struct device_desc device_desc;
static WINDOWPOS windowpos;
IDirect3DDevice8 *device;
@@ -2777,7 +2842,6 @@ static void test_wndproc(void)
HRESULT hr;
D3DDISPLAYMODE d3ddm;
DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
- DEVMODEW devmode;
LONG change_ret, device_style;
BOOL ret;
@@ -2959,6 +3023,9 @@ static void test_wndproc(void)
return;
}
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
+
filter_messages = NULL;
expect_messages = NULL;
@@ -3361,6 +3428,9 @@ done:
DestroyWindow(device_window);
DestroyWindow(focus_window);
UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_wndproc_windowed(void)
--
2.27.0
2
1
Mostly to test that when doing mode restoration, all display outputs get restored to their display
settings in the registry, not just one output gets restored.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/dxgi/tests/dxgi.c | 427 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 427 insertions(+)
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c
index 43c4247dc2a..4d9677b3762 100644
--- a/dlls/dxgi/tests/dxgi.c
+++ b/dlls/dxgi/tests/dxgi.c
@@ -134,6 +134,77 @@ static void get_virtual_rect(RECT *rect)
rect->bottom = rect->top + GetSystemMetrics(SM_CYVIRTUALSCREEN);
}
+static BOOL equal_mode_rect(const DEVMODEW *mode1, const DEVMODEW *mode2)
+{
+ return mode1->dmPosition.x == mode2->dmPosition.x
+ && mode1->dmPosition.y == mode2->dmPosition.y
+ && mode1->dmPelsWidth == mode2->dmPelsWidth
+ && mode1->dmPelsHeight == mode2->dmPelsHeight;
+}
+
+/* Free original_modes after finished using it */
+static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
+{
+ unsigned int number, size = 2, count = 0, index = 0;
+ DISPLAY_DEVICEW display_device;
+ DEVMODEW *modes, *tmp;
+
+ if (!(modes = heap_alloc(size * sizeof(*modes))))
+ return FALSE;
+
+ display_device.cb = sizeof(display_device);
+ while (EnumDisplayDevicesW(NULL, index++, &display_device, 0))
+ {
+ /* Skip software devices */
+ if (swscanf(display_device.DeviceName, L"\\\\.\\DISPLAY%u", &number) != 1)
+ continue;
+
+ if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
+ continue;
+
+ if (count >= size)
+ {
+ size *= 2;
+ if (!(tmp = heap_realloc(modes, size * sizeof(*modes))))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+ modes = tmp;
+ }
+
+ memset(&modes[count], 0, sizeof(modes[count]));
+ modes[count].dmSize = sizeof(modes[count]);
+ if (!EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &modes[count]))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+
+ lstrcpyW(modes[count++].dmDeviceName, display_device.DeviceName);
+ }
+
+ *original_modes = modes;
+ *display_count = count;
+ return TRUE;
+}
+
+static BOOL restore_display_modes(DEVMODEW *modes, unsigned int count)
+{
+ unsigned int index;
+ LONG ret;
+
+ for (index = 0; index < count; ++index)
+ {
+ ret = ChangeDisplaySettingsExW(modes[index].dmDeviceName, &modes[index], NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ if (ret != DISP_CHANGE_SUCCESSFUL)
+ return FALSE;
+ }
+ ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
+ return ret == DISP_CHANGE_SUCCESSFUL;
+}
+
/* try to make sure pending X events have been processed before continuing */
static void flush_events(void)
{
@@ -6897,6 +6968,360 @@ static void test_colour_space_support(IUnknown *device, BOOL is_d3d12)
ok(ref_count == !is_d3d12, "Factory has %u references left.\n", ref_count);
}
+static void test_mode_change(IUnknown *device, BOOL is_d3d12)
+{
+ unsigned int user32_width = 0, user32_height = 0, d3d_width = 0, d3d_height = 0;
+ unsigned int display_count = 0, mode_idx = 0, adapter_idx, output_idx;
+ DEVMODEW *original_modes = NULL, old_devmode, devmode, devmode2;
+ DXGI_SWAP_CHAIN_DESC swapchain_desc, swapchain_desc2;
+ IDXGIOutput *output, *second_output = NULL;
+ WCHAR second_monitor_name[CCHDEVICENAME];
+ IDXGISwapChain *swapchain, *swapchain2;
+ DXGI_OUTPUT_DESC output_desc;
+ IDXGIAdapter *adapter;
+ IDXGIFactory *factory;
+ BOOL fullscreen, ret;
+ LONG change_ret;
+ ULONG refcount;
+ HRESULT hr;
+
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(equal_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(equal_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+
+ while (EnumDisplaySettingsW(NULL, mode_idx++, &devmode))
+ {
+ if (devmode.dmPelsWidth == registry_mode.dmPelsWidth
+ && devmode.dmPelsHeight == registry_mode.dmPelsHeight)
+ continue;
+
+ if (!d3d_width && !d3d_height)
+ {
+ d3d_width = devmode.dmPelsWidth;
+ d3d_height = devmode.dmPelsHeight;
+ continue;
+ }
+
+ if (devmode.dmPelsWidth == d3d_width && devmode.dmPelsHeight == d3d_height)
+ continue;
+
+ user32_width = devmode.dmPelsWidth;
+ user32_height = devmode.dmPelsHeight;
+ break;
+ }
+ if (!user32_width || !user32_height)
+ {
+ skip("Failed to find three different display modes for the primary output.\n");
+ return;
+ }
+
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
+
+ get_factory(device, is_d3d12, &factory);
+
+ /* Test that no mode restorations if no mode changes actually happened */
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ swapchain_desc.BufferDesc.Width = registry_mode.dmPelsWidth;
+ swapchain_desc.BufferDesc.Height = registry_mode.dmPelsHeight;
+ swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
+ swapchain_desc.BufferDesc.RefreshRate.Denominator = 1;
+ swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
+ swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
+ swapchain_desc.SampleDesc.Count = 1;
+ swapchain_desc.SampleDesc.Quality = 0;
+ swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapchain_desc.BufferCount = is_d3d12 ? 2 : 1;
+ swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
+ swapchain_desc.Windowed = TRUE;
+ swapchain_desc.SwapEffect = is_d3d12 ? DXGI_SWAP_EFFECT_FLIP_DISCARD : DXGI_SWAP_EFFECT_DISCARD;
+ swapchain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+
+ hr = IDXGIFactory_CreateSwapChain(factory, device, &swapchain_desc, &swapchain);
+ ok(hr == S_OK, "CreateSwapChain failed, hr %#x.\n", hr);
+ refcount = IDXGISwapChain_Release(swapchain);
+ ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
+
+ memset(&devmode2, 0, sizeof(devmode2));
+ devmode2.dmSize = sizeof(devmode2);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(equal_mode_rect(&devmode2, ®istry_mode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* If current display settings are different than the display settings in registry before
+ * calling SetFullscreenState() */
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ hr = IDXGIFactory_CreateSwapChain(factory, device, &swapchain_desc, &swapchain);
+ ok(hr == S_OK, "CreateSwapChain failed, hr %#x.\n", hr);
+ hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
+ ok(hr == DXGI_ERROR_UNSUPPORTED /* Win7 */
+ || hr == S_OK /* Win8~Win10 1909 */
+ || hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE, /* Win10 2004 */
+ "Got unexpected hr %#x.\n", hr);
+
+ hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+ refcount = IDXGISwapChain_Release(swapchain);
+ ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry with a fullscreen device */
+ hr = IDXGIFactory_CreateSwapChain(factory, device, &swapchain_desc, &swapchain);
+ ok(hr == S_OK, "CreateSwapChain failed, hr %#x.\n", hr);
+ hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
+ if (FAILED(hr))
+ {
+ skip("SetFullscreenState failed, hr %#x.\n", hr);
+ refcount = IDXGISwapChain_Release(swapchain);
+ ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
+ goto done;
+ }
+
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+ hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ refcount = IDXGISwapChain_Release(swapchain);
+ ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ for (adapter_idx = 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory, adapter_idx, &adapter)); ++adapter_idx)
+ {
+ for (output_idx = 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter, output_idx, &output)); ++output_idx)
+ {
+ hr = IDXGIOutput_GetDesc(output, &output_desc);
+ ok(hr == S_OK, "Adapter %u output %u: Got unexpected hr %#x.\n", adapter_idx, output_idx, hr);
+
+ if ((adapter_idx || output_idx) && output_desc.AttachedToDesktop)
+ {
+ second_output = output;
+ break;
+ }
+
+ IDXGIOutput_Release(output);
+ }
+
+ IDXGIAdapter_Release(adapter);
+ if (second_output)
+ break;
+ }
+
+ if (!second_output)
+ {
+ skip("Following tests require two monitors.\n");
+ goto done;
+ }
+ lstrcpyW(second_monitor_name, output_desc.DeviceName);
+
+ memset(&old_devmode, 0, sizeof(old_devmode));
+ old_devmode.dmSize = sizeof(old_devmode);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &old_devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+
+ mode_idx = 0;
+ d3d_width = 0;
+ d3d_height = 0;
+ user32_width = 0;
+ user32_height = 0;
+ while (EnumDisplaySettingsW(second_monitor_name, mode_idx++, &devmode))
+ {
+ if (devmode.dmPelsWidth == old_devmode.dmPelsWidth
+ && devmode.dmPelsHeight == old_devmode.dmPelsHeight)
+ continue;
+
+ if (!d3d_width && !d3d_height)
+ {
+ d3d_width = devmode.dmPelsWidth;
+ d3d_height = devmode.dmPelsHeight;
+ continue;
+ }
+
+ if (devmode.dmPelsWidth == d3d_width && devmode.dmPelsHeight == d3d_height)
+ continue;
+
+ user32_width = devmode.dmPelsWidth;
+ user32_height = devmode.dmPelsHeight;
+ break;
+ }
+ if (!user32_width || !user32_height)
+ {
+ skip("Failed to find three different display modes for the second output.\n");
+ goto done;
+ }
+
+ /* Test that mode restorations for non-primary outputs upon fullscreen state changes */
+ hr = IDXGIFactory_CreateSwapChain(factory, device, &swapchain_desc, &swapchain);
+ ok(hr == S_OK, "CreateSwapChain failed, hr %#x.\n", hr);
+ hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ if (devmode2.dmPelsWidth == old_devmode.dmPelsWidth
+ && devmode2.dmPelsHeight == old_devmode.dmPelsHeight)
+ {
+ skip("Failed to change display settings of the second monitor.\n");
+ hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+ refcount = IDXGISwapChain_Release(swapchain);
+ ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
+ goto done;
+ }
+
+ hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ hr = IDXGIOutput_GetDesc(second_output, &output_desc);
+ ok(hr == S_OK, "GetDesc failed, hr %#x.\n", hr);
+ todo_wine ok(output_desc.DesktopCoordinates.right - output_desc.DesktopCoordinates.left ==
+ old_devmode.dmPelsWidth, "Expected width %u, got %u.\n", old_devmode.dmPelsWidth,
+ output_desc.DesktopCoordinates.right - output_desc.DesktopCoordinates.left);
+ todo_wine ok(output_desc.DesktopCoordinates.bottom - output_desc.DesktopCoordinates.top ==
+ old_devmode.dmPelsHeight, "Expected height %u, got %u.\n", old_devmode.dmPelsHeight,
+ output_desc.DesktopCoordinates.bottom - output_desc.DesktopCoordinates.top);
+
+ refcount = IDXGISwapChain_Release(swapchain);
+ ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations for non-primary outputs use display settings in the registry */
+ hr = IDXGIFactory_CreateSwapChain(factory, device, &swapchain_desc, &swapchain);
+ ok(hr == S_OK, "CreateSwapChain failed, hr %#x.\n", hr);
+ hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
+ ok(hr == S_OK, "SetFullscreenState failed, hr %#x.\n", hr);
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+ hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
+ ok(hr == S_OK, "SetFullscreenState failed, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ hr = IDXGIOutput_GetDesc(second_output, &output_desc);
+ ok(hr == S_OK, "GetDesc failed, hr %#x.\n", hr);
+ todo_wine ok(output_desc.DesktopCoordinates.right - output_desc.DesktopCoordinates.left ==
+ devmode.dmPelsWidth, "Expected width %u, got %u.\n", devmode.dmPelsWidth,
+ output_desc.DesktopCoordinates.right - output_desc.DesktopCoordinates.left);
+ todo_wine ok(output_desc.DesktopCoordinates.bottom - output_desc.DesktopCoordinates.top ==
+ devmode.dmPelsHeight, "Expected height %u, got %u.\n", devmode.dmPelsHeight,
+ output_desc.DesktopCoordinates.bottom - output_desc.DesktopCoordinates.top);
+
+ refcount = IDXGISwapChain_Release(swapchain);
+ ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations for non-primary outputs on fullscreen state changes when there
+ * are two fullscreen swapchains on different outputs */
+ hr = IDXGIFactory_CreateSwapChain(factory, device, &swapchain_desc, &swapchain);
+ ok(hr == S_OK, "CreateSwapChain failed, hr %#x.\n", hr);
+
+ swapchain_desc2 = swapchain_desc;
+ swapchain_desc.BufferDesc.Width = d3d_width;
+ swapchain_desc.BufferDesc.Height = d3d_height;
+ swapchain_desc2.OutputWindow = CreateWindowA("static", "dxgi_test2", 0,
+ old_devmode.dmPosition.x, old_devmode.dmPosition.y, 400, 200, 0, 0, 0, 0);
+ hr = IDXGIFactory_CreateSwapChain(factory, device, &swapchain_desc2, &swapchain2);
+ ok(hr == S_OK, "CreateSwapChain failed, hr %#x.\n", hr);
+ hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
+ ok(hr == S_OK, "SetFullscreenState failed, hr %#x.\n", hr);
+ hr = IDXGISwapChain_SetFullscreenState(swapchain2, TRUE, NULL);
+ if (FAILED(hr))
+ {
+ skip("SetFullscreenState failed, hr %#x.\n", hr);
+ refcount = IDXGISwapChain_Release(swapchain2);
+ ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
+ hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
+ ok(hr == S_OK, "SetFullscreenState failed, hr %#x.\n", hr);
+ refcount = IDXGISwapChain_Release(swapchain);
+ ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
+ goto done;
+ }
+
+ hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
+ ok(hr == S_OK, "SetFullscreenState failed, hr %#x.\n", hr);
+ hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
+ ok(hr == S_OK, "GetFullscreenState failed, hr %#x.\n", hr);
+ ok(!fullscreen, "Expected swapchain not fullscreen.\n");
+ hr = IDXGISwapChain_GetFullscreenState(swapchain2, &fullscreen, NULL);
+ ok(hr == S_OK, "GetFullscreenState failed, hr %#x.\n", hr);
+ ok(fullscreen, "Expected swapchain fullscreen.\n");
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ hr = IDXGIOutput_GetDesc(second_output, &output_desc);
+ ok(hr == S_OK, "GetDesc failed, hr %#x.\n", hr);
+ ok(output_desc.DesktopCoordinates.right - output_desc.DesktopCoordinates.left ==
+ old_devmode.dmPelsWidth, "Expected width %u, got %u.\n", old_devmode.dmPelsWidth,
+ output_desc.DesktopCoordinates.right - output_desc.DesktopCoordinates.left);
+ ok(output_desc.DesktopCoordinates.bottom - output_desc.DesktopCoordinates.top ==
+ old_devmode.dmPelsHeight, "Expected height %u, got %u.\n", old_devmode.dmPelsHeight,
+ output_desc.DesktopCoordinates.bottom - output_desc.DesktopCoordinates.top);
+
+ hr = IDXGISwapChain_SetFullscreenState(swapchain2, FALSE, NULL);
+ ok(hr == S_OK, "SetFullscreenState failed, hr %#x.\n", hr);
+ refcount = IDXGISwapChain_Release(swapchain2);
+ ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
+ refcount = IDXGISwapChain_Release(swapchain);
+ ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
+ DestroyWindow(swapchain_desc2.OutputWindow);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+done:
+ if (second_output)
+ IDXGIOutput_Release(second_output);
+ DestroyWindow(swapchain_desc.OutputWindow);
+ refcount = IDXGIFactory_Release(factory);
+ ok(refcount == !is_d3d12, "Got unexpected refcount %u.\n", refcount);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
+}
+
static void run_on_d3d10(void (*test_func)(IUnknown *device, BOOL is_d3d12))
{
IDXGIDevice *device;
@@ -7013,6 +7438,7 @@ START_TEST(dxgi)
run_on_d3d10(test_get_containing_output);
run_on_d3d10(test_window_association);
run_on_d3d10(test_default_fullscreen_target_output);
+ run_on_d3d10(test_mode_change);
if (!(d3d12_module = LoadLibraryA("d3d12.dll")))
{
@@ -7042,6 +7468,7 @@ START_TEST(dxgi)
run_on_d3d12(test_get_containing_output);
run_on_d3d12(test_window_association);
run_on_d3d12(test_default_fullscreen_target_output);
+ run_on_d3d12(test_mode_change);
FreeLibrary(d3d12_module);
}
--
2.27.0
1
0
Mostly to test that when doing mode restoration, all display outputs get restored to their display
settings in the registry, not just one output gets restored.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/d3d9/tests/device.c | 385 +++++++++++++++++++++++++++++++++++++--
1 file changed, 373 insertions(+), 12 deletions(-)
diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c
index 0f0de5e3382..d7b71152b03 100644
--- a/dlls/d3d9/tests/device.c
+++ b/dlls/d3d9/tests/device.c
@@ -159,6 +159,14 @@ static BOOL adapter_is_warp(const D3DADAPTER_IDENTIFIER9 *identifier)
return !strcmp(identifier->Driver, "d3d10warp.dll");
}
+static BOOL equal_mode_rect(const DEVMODEW *mode1, const DEVMODEW *mode2)
+{
+ return mode1->dmPosition.x == mode2->dmPosition.x
+ && mode1->dmPosition.y == mode2->dmPosition.y
+ && mode1->dmPelsWidth == mode2->dmPelsWidth
+ && mode1->dmPelsHeight == mode2->dmPelsHeight;
+}
+
/* Free original_modes after finished using it */
static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
{
@@ -5267,21 +5275,34 @@ done:
static void test_mode_change(void)
{
+ DEVMODEW old_devmode, devmode, devmode2, *original_modes = NULL;
+ struct device_desc device_desc, device_desc2;
+ WCHAR second_monitor_name[CCHDEVICENAME];
+ IDirect3DDevice9 *device, *device2;
+ unsigned int display_count = 0;
RECT d3d_rect, focus_rect, r;
- struct device_desc device_desc;
IDirect3DSurface9 *backbuffer;
- IDirect3DDevice9 *device;
+ MONITORINFOEXW monitor_info;
+ HMONITOR second_monitor;
D3DSURFACE_DESC desc;
IDirect3D9 *d3d9;
- DEVMODEW devmode;
ULONG refcount;
UINT adapter_mode_count, i;
HRESULT hr;
- DWORD ret;
+ BOOL ret;
LONG change_ret;
D3DDISPLAYMODE d3ddm;
DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(equal_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(equal_mode_rect(&devmode, ®istry_mode), "Got a different mode.\n");
+
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
ok(!!d3d9, "Failed to create a D3D object.\n");
@@ -5334,6 +5355,9 @@ static void test_mode_change(void)
return;
}
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
+
memset(&devmode, 0, sizeof(devmode));
devmode.dmSize = sizeof(devmode);
devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
@@ -5358,8 +5382,6 @@ static void test_mode_change(void)
if (!(device = create_device(d3d9, focus_window, &device_desc)))
{
skip("Failed to create a D3D device, skipping tests.\n");
- change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
- ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
goto done;
}
@@ -5411,8 +5433,13 @@ static void test_mode_change(void)
device_desc.width = registry_mode.dmPelsWidth;
device_desc.height = registry_mode.dmPelsHeight;
device_desc.flags = CREATE_DEVICE_FULLSCREEN;
- ok(!!(device = create_device(d3d9, focus_window, &device_desc)), "Failed to create a D3D device.\n");
+ if (!(device = create_device(d3d9, focus_window, &device_desc)))
+ {
+ skip("Failed to create a D3D device, skipping tests.\n");
+ goto done;
+ }
+ devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
devmode.dmPelsWidth = user32_width;
devmode.dmPelsHeight = user32_height;
change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
@@ -5421,17 +5448,351 @@ static void test_mode_change(void)
refcount = IDirect3DDevice9_Release(device);
ok(!refcount, "Device has %u references left.\n", refcount);
- ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+ memset(&devmode2, 0, sizeof(devmode2));
+ devmode2.dmSize = sizeof(devmode2);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
ok(ret, "Failed to get display mode.\n");
- ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
- && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
- "Expected resolution %ux%u, got %ux%u.\n",
- registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
+ ok(devmode2.dmPelsWidth == registry_mode.dmPelsWidth
+ && devmode2.dmPelsHeight == registry_mode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", registry_mode.dmPelsWidth,
+ registry_mode.dmPelsHeight, devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that no mode restorations if no mode changes happened */
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
+ device_desc.device_window = device_window;
+ device_desc.width = d3d_width;
+ device_desc.height = d3d_height;
+ device_desc.flags = 0;
+ device = create_device(d3d9, device_window, &device_desc);
+ ok(!!device, "Failed to create a D3D device.\n");
+ refcount = IDirect3DDevice9_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(equal_mode_rect(&devmode2, ®istry_mode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry with a fullscreen device */
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
+ device_desc.device_window = device_window;
+ device_desc.width = registry_mode.dmPelsWidth;
+ device_desc.height = registry_mode.dmPelsHeight;
+ device_desc.flags = CREATE_DEVICE_FULLSCREEN;
+ if (!(device = create_device(d3d9, device_window, &device_desc)))
+ {
+ skip("Failed to create a D3D device, skipping tests.\n");
+ goto done;
+ }
+ refcount = IDirect3DDevice9_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations use display settings in the registry with a fullscreen device
+ * having the same display mode and then reset to a different mode */
+ change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %d.\n", change_ret);
+
+ device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
+ device_desc.device_window = device_window;
+ device_desc.width = registry_mode.dmPelsWidth;
+ device_desc.height = registry_mode.dmPelsHeight;
+ device_desc.flags = CREATE_DEVICE_FULLSCREEN;
+ if (!(device = create_device(d3d9, device_window, &device_desc)))
+ {
+ skip("Failed to create a D3D device, skipping tests.\n");
+ goto done;
+ }
+
+ device_desc.width = d3d_width;
+ device_desc.height = d3d_height;
+ hr = reset_device(device, &device_desc);
+ ok(hr == D3D_OK, "Failed to reset device, hr %#x.\n", hr);
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(devmode2.dmPelsWidth == d3d_width && devmode2.dmPelsHeight == d3d_height,
+ "Expected resolution %ux%u, got %ux%u.\n", d3d_width, d3d_height,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+
+ refcount = IDirect3DDevice9_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+
+ ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ if (IDirect3D9_GetAdapterCount(d3d9) < 2)
+ {
+ skip("Following tests require two adapters.\n");
+ goto done;
+ }
+
+ second_monitor = IDirect3D9_GetAdapterMonitor(d3d9, 1);
+ monitor_info.cbSize = sizeof(monitor_info);
+ ret = GetMonitorInfoW(second_monitor, (MONITORINFO *)&monitor_info);
+ ok(ret, "GetMonitorInfoW failed, error %#x.\n", GetLastError());
+ lstrcpyW(second_monitor_name, monitor_info.szDevice);
+
+ memset(&old_devmode, 0, sizeof(old_devmode));
+ old_devmode.dmSize = sizeof(old_devmode);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &old_devmode);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+
+ i = 0;
+ d3d_width = 0;
+ d3d_height = 0;
+ user32_width = 0;
+ user32_height = 0;
+ while (EnumDisplaySettingsW(second_monitor_name, i++, &devmode))
+ {
+ if (devmode.dmPelsWidth == old_devmode.dmPelsWidth
+ && devmode.dmPelsHeight == old_devmode.dmPelsHeight)
+ continue;
+
+ if (!d3d_width && !d3d_height)
+ {
+ d3d_width = devmode.dmPelsWidth;
+ d3d_height = devmode.dmPelsHeight;
+ continue;
+ }
+
+ if (devmode.dmPelsWidth == d3d_width && devmode.dmPelsHeight == d3d_height)
+ continue;
+
+ user32_width = devmode.dmPelsWidth;
+ user32_height = devmode.dmPelsHeight;
+ break;
+ }
+ if (!user32_width || !user32_height)
+ {
+ skip("Failed to find three different display modes for the second monitor.\n");
+ goto done;
+ }
+
+ /* Test that mode restorations also happen for non-primary monitors on device resets */
+ device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
+ device_desc.device_window = device_window;
+ device_desc.width = registry_mode.dmPelsWidth;
+ device_desc.height = registry_mode.dmPelsHeight;
+ device_desc.flags = CREATE_DEVICE_FULLSCREEN;
+ if (!(device = create_device(d3d9, device_window, &device_desc)))
+ {
+ skip("Failed to create a D3D device.\n");
+ goto done;
+ }
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ if (devmode2.dmPelsWidth == old_devmode.dmPelsWidth
+ && devmode2.dmPelsHeight == old_devmode.dmPelsHeight)
+ {
+ skip("Failed to change display settings of the second monitor.\n");
+ refcount = IDirect3DDevice9_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ goto done;
+ }
+
+ device_desc.flags = 0;
+ hr = reset_device(device, &device_desc);
+ ok(hr == D3D_OK, "Failed to reset device, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ hr = IDirect3D9_GetAdapterDisplayMode(d3d9, 1, &d3ddm);
+ ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#x.\n", hr);
+ todo_wine ok(d3ddm.Width == old_devmode.dmPelsWidth, "Expected width %u, got %u.\n",
+ old_devmode.dmPelsWidth, d3ddm.Width);
+ todo_wine ok(d3ddm.Height == old_devmode.dmPelsHeight, "Expected height %u, got %u.\n",
+ old_devmode.dmPelsHeight, d3ddm.Height);
+
+ refcount = IDirect3DDevice9_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations happen for non-primary monitors on device releases */
+ device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
+ device_desc.device_window = device_window;
+ device_desc.width = registry_mode.dmPelsWidth;
+ device_desc.height = registry_mode.dmPelsHeight;
+ device_desc.flags = CREATE_DEVICE_FULLSCREEN;
+ if (!(device = create_device(d3d9, device_window, &device_desc)))
+ {
+ skip("Failed to create a D3D device.\n");
+ goto done;
+ }
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ refcount = IDirect3DDevice9_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ hr = IDirect3D9_GetAdapterDisplayMode(d3d9, 1, &d3ddm);
+ ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#x.\n", hr);
+ todo_wine ok(d3ddm.Width == old_devmode.dmPelsWidth, "Expected width %u, got %u.\n",
+ old_devmode.dmPelsWidth, d3ddm.Width);
+ todo_wine ok(d3ddm.Height == old_devmode.dmPelsHeight, "Expected height %u, got %u.\n",
+ old_devmode.dmPelsHeight, d3ddm.Height);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test that mode restorations for non-primary monitors use display settings in the registry */
+ if (!(device = create_device(d3d9, device_window, &device_desc)))
+ {
+ skip("Failed to create a D3D device.\n");
+ goto done;
+ }
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ refcount = IDirect3DDevice9_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ devmode2.dmPelsWidth, devmode2.dmPelsHeight);
+ hr = IDirect3D9_GetAdapterDisplayMode(d3d9, 1, &d3ddm);
+ ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#x.\n", hr);
+ todo_wine ok(d3ddm.Width == devmode.dmPelsWidth && d3ddm.Height == devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
+ d3ddm.Width, d3ddm.Height);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test mode restorations when there are two fullscreen devices and one of them got reset */
+ if (!(device = create_device(d3d9, focus_window, &device_desc)))
+ {
+ skip("Failed to create a D3D device.\n");
+ goto done;
+ }
+
+ device_desc2.adapter_ordinal = 1;
+ device_desc2.device_window = device_window;
+ device_desc2.width = d3d_width;
+ device_desc2.height = d3d_height;
+ device_desc2.flags = CREATE_DEVICE_FULLSCREEN;
+ if (!(device2 = create_device(d3d9, focus_window, &device_desc2)))
+ {
+ skip("Failed to create a D3D device.\n");
+ refcount = IDirect3DDevice9_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ goto done;
+ }
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ device_desc.flags = 0;
+ hr = reset_device(device, &device_desc);
+ ok(hr == D3D_OK, "Failed to reset device, hr %#x.\n", hr);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ hr = IDirect3D9_GetAdapterDisplayMode(d3d9, 1, &d3ddm);
+ ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#x.\n", hr);
+ todo_wine ok(d3ddm.Width == old_devmode.dmPelsWidth && d3ddm.Height == old_devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", old_devmode.dmPelsWidth,
+ old_devmode.dmPelsHeight, d3ddm.Width, d3ddm.Height);
+
+ refcount = IDirect3DDevice9_Release(device2);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ refcount = IDirect3DDevice9_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+
+ /* Test mode restoration when there are two fullscreen devices and one of them got released */
+ device_desc.flags = CREATE_DEVICE_FULLSCREEN;
+ if (!(device = create_device(d3d9, focus_window, &device_desc)))
+ {
+ skip("Failed to create a D3D device.\n");
+ goto done;
+ }
+
+ if (!(device2 = create_device(d3d9, focus_window, &device_desc2)))
+ {
+ skip("Failed to create a D3D device.\n");
+ refcount = IDirect3DDevice9_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ goto done;
+ }
+
+ change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
+ ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %d.\n", change_ret);
+
+ refcount = IDirect3DDevice9_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ todo_wine ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
+ ok(ret, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
+ ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
+ hr = IDirect3D9_GetAdapterDisplayMode(d3d9, 1, &d3ddm);
+ ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#x.\n", hr);
+ todo_wine ok(d3ddm.Width == old_devmode.dmPelsWidth && d3ddm.Height == old_devmode.dmPelsHeight,
+ "Expected resolution %ux%u, got %ux%u.\n", old_devmode.dmPelsWidth,
+ old_devmode.dmPelsHeight, d3ddm.Width, d3ddm.Height);
+
+ refcount = IDirect3DDevice9_Release(device2);
+ ok(!refcount, "Device has %u references left.\n", refcount);
done:
DestroyWindow(device_window);
DestroyWindow(focus_window);
IDirect3D9_Release(d3d9);
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_device_window_reset(void)
--
2.27.0
1
0
[PATCH 2/8] d3d9/tests: Restore display modes at the end of test_wndproc().
by Zhiyi Zhang Oct. 28, 2020
by Zhiyi Zhang Oct. 28, 2020
Oct. 28, 2020
test_wndproc() makes a series of ChangeDisplaySettings() calls that could make the current display
mode no longer match the registry display mode. Restore display modes at the end of test_wndproc()
so that other tests are not affected.
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/d3d9/tests/device.c | 73 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 72 insertions(+), 1 deletion(-)
diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c
index 53a83ad887b..0f0de5e3382 100644
--- a/dlls/d3d9/tests/device.c
+++ b/dlls/d3d9/tests/device.c
@@ -25,6 +25,7 @@
#define COBJMACROS
#include <d3d9.h>
#include "utils.h"
+#include "wine/heap.h"
struct vec3
{
@@ -158,6 +159,69 @@ static BOOL adapter_is_warp(const D3DADAPTER_IDENTIFIER9 *identifier)
return !strcmp(identifier->Driver, "d3d10warp.dll");
}
+/* Free original_modes after finished using it */
+static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
+{
+ unsigned int number, size = 2, count = 0, index = 0;
+ DISPLAY_DEVICEW display_device;
+ DEVMODEW *modes, *tmp;
+
+ if (!(modes = heap_alloc(size * sizeof(*modes))))
+ return FALSE;
+
+ display_device.cb = sizeof(display_device);
+ while (EnumDisplayDevicesW(NULL, index++, &display_device, 0))
+ {
+ /* Skip software devices */
+ if (swscanf(display_device.DeviceName, L"\\\\.\\DISPLAY%u", &number) != 1)
+ continue;
+
+ if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
+ continue;
+
+ if (count >= size)
+ {
+ size *= 2;
+ if (!(tmp = heap_realloc(modes, size * sizeof(*modes))))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+ modes = tmp;
+ }
+
+ memset(&modes[count], 0, sizeof(modes[count]));
+ modes[count].dmSize = sizeof(modes[count]);
+ if (!EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &modes[count]))
+ {
+ heap_free(modes);
+ return FALSE;
+ }
+
+ lstrcpyW(modes[count++].dmDeviceName, display_device.DeviceName);
+ }
+
+ *original_modes = modes;
+ *display_count = count;
+ return TRUE;
+}
+
+static BOOL restore_display_modes(DEVMODEW *modes, unsigned int count)
+{
+ unsigned int index;
+ LONG ret;
+
+ for (index = 0; index < count; ++index)
+ {
+ ret = ChangeDisplaySettingsExW(modes[index].dmDeviceName, &modes[index], NULL,
+ CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+ if (ret != DISP_CHANGE_SUCCESSFUL)
+ return FALSE;
+ }
+ ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
+ return ret == DISP_CHANGE_SUCCESSFUL;
+}
+
static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND focus_window, const struct device_desc *desc)
{
D3DPRESENT_PARAMETERS present_parameters = {0};
@@ -3758,6 +3822,8 @@ static DWORD WINAPI wndproc_thread(void *param)
static void test_wndproc(void)
{
struct wndproc_thread_param thread_params;
+ DEVMODEW devmode, *original_modes = NULL;
+ unsigned int display_count = 0;
struct device_desc device_desc;
static WINDOWPOS windowpos;
IDirect3DDevice9 *device;
@@ -3772,7 +3838,6 @@ static void test_wndproc(void)
HRESULT hr;
D3DDISPLAYMODE d3ddm;
DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
- DEVMODEW devmode;
LONG change_ret, device_style;
BOOL ret;
@@ -3997,6 +4062,9 @@ static void test_wndproc(void)
return;
}
+ ret = save_display_modes(&original_modes, &display_count);
+ ok(ret, "Failed to save original display modes.\n");
+
filter_messages = NULL;
expect_messages = NULL;
@@ -4435,6 +4503,9 @@ done:
CloseHandle(thread_params.test_finished);
CloseHandle(thread_params.window_created);
UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
+ ret = restore_display_modes(original_modes, display_count);
+ ok(ret, "Failed to restore display modes.\n");
+ heap_free(original_modes);
}
static void test_wndproc_windowed(void)
--
2.27.0
1
0
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
configure | 2 ++
configure.ac | 1 +
dlls/wow64cpu/Makefile.in | 7 +++++++
dlls/wow64cpu/wow64cpu.spec | 25 +++++++++++++++++++++++++
dlls/wow64cpu/wow64cpu_main.c | 27 +++++++++++++++++++++++++++
5 files changed, 62 insertions(+)
create mode 100644 dlls/wow64cpu/Makefile.in
create mode 100644 dlls/wow64cpu/wow64cpu.spec
create mode 100644 dlls/wow64cpu/wow64cpu_main.c
diff --git a/configure b/configure
index ac6a7985cc7..8bff0297bef 100755
--- a/configure
+++ b/configure
@@ -1692,6 +1692,7 @@ enable_wmp
enable_wmphoto
enable_wmvcore
enable_wnaspi32
+enable_wow64cpu
enable_wpc
enable_wpcap
enable_ws2_32
@@ -21142,6 +21143,7 @@ wine_fn_config_makefile dlls/wmvcore enable_wmvcore
wine_fn_config_makefile dlls/wmvcore/tests enable_tests
wine_fn_config_makefile dlls/wnaspi32 enable_wnaspi32
wine_fn_config_makefile dlls/wow32 enable_win16
+wine_fn_config_makefile dlls/wow64cpu enable_wow64cpu
wine_fn_config_makefile dlls/wpc enable_wpc
wine_fn_config_makefile dlls/wpc/tests enable_tests
wine_fn_config_makefile dlls/wpcap enable_wpcap
diff --git a/configure.ac b/configure.ac
index 2f81fd22610..7b7abeb11ed 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3885,6 +3885,7 @@ WINE_CONFIG_MAKEFILE(dlls/wmvcore)
WINE_CONFIG_MAKEFILE(dlls/wmvcore/tests)
WINE_CONFIG_MAKEFILE(dlls/wnaspi32)
WINE_CONFIG_MAKEFILE(dlls/wow32,enable_win16)
+WINE_CONFIG_MAKEFILE(dlls/wow64cpu)
WINE_CONFIG_MAKEFILE(dlls/wpc)
WINE_CONFIG_MAKEFILE(dlls/wpc/tests)
WINE_CONFIG_MAKEFILE(dlls/wpcap)
diff --git a/dlls/wow64cpu/Makefile.in b/dlls/wow64cpu/Makefile.in
new file mode 100644
index 00000000000..2ab1ca62c4a
--- /dev/null
+++ b/dlls/wow64cpu/Makefile.in
@@ -0,0 +1,7 @@
+MODULE = wow64cpu.dll
+IMPORTS = winecrt0 ntdll
+
+EXTRADLLFLAGS = -nodefaultlibs -mno-cygwin
+
+C_SRCS = \
+ wow64cpu_main.c
diff --git a/dlls/wow64cpu/wow64cpu.spec b/dlls/wow64cpu/wow64cpu.spec
new file mode 100644
index 00000000000..0ea2b4defc6
--- /dev/null
+++ b/dlls/wow64cpu/wow64cpu.spec
@@ -0,0 +1,25 @@
+# @ stub CpuFlushInstructionCache
+# @ stub CpuGetContext
+# @ stub CpuGetStackPointer
+# @ stub CpuInitializeStartupContext
+# @ stub CpuNotifyAffinityChange
+# @ stub CpuNotifyAfterFork
+# @ stub CpuNotifyBeforeFork
+# @ stub CpuNotifyDllLoad
+# @ stub CpuNotifyDllUnload
+# @ stub CpuPrepareForDebuggerAttach
+# @ stub CpuProcessDebugEvent
+# @ stub CpuProcessInit
+# @ stub CpuProcessTerm
+# @ stub CpuResetFloatingPoint
+# @ stub CpuResetToConsistentState
+# @ stub CpuSetContext
+# @ stub CpuSetInstructionPointer
+# @ stub CpuSetStackPointer
+# @ stub CpuSimulate
+# @ stub CpuSuspendLocalThread
+# @ stub CpuSuspendThread
+# @ stub CpuThreadInit
+# @ stub CpuThreadTerm
+# @ stub TurboDispatchJumpAddressEnd
+# @ stub TurboDispatchJumpAddressStart
diff --git a/dlls/wow64cpu/wow64cpu_main.c b/dlls/wow64cpu/wow64cpu_main.c
new file mode 100644
index 00000000000..4da9695230b
--- /dev/null
+++ b/dlls/wow64cpu/wow64cpu_main.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2018 Zebediah Figura
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+#include "windef.h"
+#include "winternl.h"
+
+BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, void *reserved )
+{
+ if (reason == DLL_PROCESS_ATTACH) LdrDisableThreadCalloutsForDll( inst );
+ return TRUE;
+}
--
2.28.0
2
3
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/powrprof/powrprof.c | 23 +++++------------------
1 file changed, 5 insertions(+), 18 deletions(-)
diff --git a/dlls/powrprof/powrprof.c b/dlls/powrprof/powrprof.c
index 5f00c7b6317..fc6f5706f87 100644
--- a/dlls/powrprof/powrprof.c
+++ b/dlls/powrprof/powrprof.c
@@ -45,20 +45,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(powrprof);
* implementing these functions is going to have to wait until somebody can
* cobble together some sane test input. */
-static const WCHAR szPowerCfgSubKey[] = { 'S', 'o', 'f', 't', 'w', 'a', 'r', 'e',
- '\\', 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\', 'W', 'i',
- 'n', 'd', 'o', 'w', 's', '\\', 'C', 'u', 'r', 'r', 'e', 'n', 't',
- 'V', 'e', 'r', 's', 'i', 'o', 'n', '\\', 'C', 'o', 'n', 't', 'r',
- 'o', 'l', 's', ' ', 'F', 'o', 'l', 'd', 'e', 'r', '\\', 'P', 'o',
- 'w', 'e', 'r', 'C', 'f', 'g', 0 };
-static const WCHAR szSemaphoreName[] = { 'P', 'o', 'w', 'e', 'r', 'P', 'r', 'o',
- 'f', 'i', 'l', 'e', 'R', 'e', 'g', 'i', 's', 't', 'r', 'y', 'S',
- 'e', 'm', 'a', 'p', 'h', 'o', 'r', 'e', 0 };
-static const WCHAR szDiskMax[] = { 'D', 'i', 's', 'k', 'S', 'p', 'i', 'n', 'd',
- 'o', 'w', 'n', 'M', 'a', 'x', 0 };
-static const WCHAR szDiskMin[] = { 'D', 'i', 's', 'k', 'S', 'p', 'i', 'n', 'd',
- 'o', 'w', 'n', 'M', 'i', 'n', 0 };
-static const WCHAR szLastID[] = { 'L', 'a', 's', 't', 'I', 'D', 0 };
+static const WCHAR szPowerCfgSubKey[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Controls Folder\\PowerCfg";
static HANDLE PPRegSemaphore = NULL;
NTSTATUS WINAPI CallNtPowerInformation(
@@ -172,7 +159,7 @@ BOOLEAN WINAPI GetPwrDiskSpindownRange(PUINT RangeMax, PUINT RangeMin)
return TRUE;
}
- r = RegQueryValueExW(hKey, szDiskMax, 0, 0, lpValue, &cbValue);
+ r = RegQueryValueExW(hKey, L"DiskSpindownMax", 0, 0, lpValue, &cbValue);
if (r != ERROR_SUCCESS) {
TRACE("Couldn't open DiskSpinDownMax: %d\n", r);
TRACE("Using default: 3600\n");
@@ -183,7 +170,7 @@ BOOLEAN WINAPI GetPwrDiskSpindownRange(PUINT RangeMax, PUINT RangeMin)
cbValue = sizeof(lpValue);
- r = RegQueryValueExW(hKey, szDiskMin, 0, 0, lpValue, &cbValue);
+ r = RegQueryValueExW(hKey, L"DiskSpindownMin", 0, 0, lpValue, &cbValue);
if (r != ERROR_SUCCESS) {
TRACE("Couldn't open DiskSpinDownMin: %d\n", r);
TRACE("Using default: 3\n");
@@ -360,14 +347,14 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
} else {
BYTE lpValue[40];
DWORD cbValue = sizeof(lpValue);
- r = RegQueryValueExW(hKey, szLastID, 0, 0, lpValue, &cbValue);
+ r = RegQueryValueExW(hKey, L"LastID", 0, 0, lpValue, &cbValue);
if (r != ERROR_SUCCESS) {
TRACE("Couldn't open registry entry HKLM\\%s\\LastID, using some sane(?) defaults\n", debugstr_w(szPowerCfgSubKey));
}
RegCloseKey(hKey);
}
- PPRegSemaphore = CreateSemaphoreW(NULL, 1, 1, szSemaphoreName);
+ PPRegSemaphore = CreateSemaphoreW(NULL, 1, 1, L"PowerProfileRegistrySemaphore");
if (PPRegSemaphore == NULL) {
ERR("Couldn't create Semaphore: %d\n", GetLastError());
return FALSE;
--
2.26.2
1
0