[PATCH 8/8] [WinHlp32]: now manage windows with refcounts

Eric Pouech eric.pouech at orange.fr
Sat May 30 07:27:04 CDT 2009




A+
---

 programs/winhlp32/macro.c     |    6 ++--
 programs/winhlp32/macro.lex.l |    3 +-
 programs/winhlp32/winhelp.c   |   67 +++++++++++++++++++++++++++++++----------
 programs/winhlp32/winhelp.h   |    3 ++
 4 files changed, 59 insertions(+), 20 deletions(-)


diff --git a/programs/winhlp32/macro.c b/programs/winhlp32/macro.c
index 3383545..c2fc3cc 100644
--- a/programs/winhlp32/macro.c
+++ b/programs/winhlp32/macro.c
@@ -281,7 +281,7 @@ static void CALLBACK MACRO_CloseSecondarys(void)
     WINE_TRACE("()\n");
     for (win = Globals.win_list; win; win = win->next)
         if (lstrcmpi(win->info->name, "main"))
-            DestroyWindow(win->hMainWnd);
+            WINHELP_ReleaseWindow(win);
 }
 
 static void CALLBACK MACRO_CloseWindow(LPCSTR lpszWindow)
@@ -294,7 +294,7 @@ static void CALLBACK MACRO_CloseWindow(LPCSTR lpszWindow)
 
     for (win = Globals.win_list; win; win = win->next)
         if (!lstrcmpi(win->info->name, lpszWindow))
-            DestroyWindow(win->hMainWnd);
+            WINHELP_ReleaseWindow(win);
 }
 
 static void CALLBACK MACRO_Compare(LPCSTR str)
@@ -367,7 +367,7 @@ void CALLBACK MACRO_Exit(void)
     WINE_TRACE("()\n");
 
     while (Globals.win_list)
-        DestroyWindow(Globals.win_list->hMainWnd);
+        WINHELP_ReleaseWindow(Globals.win_list);
 }
 
 static void CALLBACK MACRO_ExtAbleItem(LPCSTR str, LONG u)
diff --git a/programs/winhlp32/macro.lex.l b/programs/winhlp32/macro.lex.l
index bf65fa0..67926cb 100644
--- a/programs/winhlp32/macro.lex.l
+++ b/programs/winhlp32/macro.lex.l
@@ -285,7 +285,7 @@ BOOL MACRO_ExecuteMacro(WINHELP_WINDOW* window, LPCSTR macro)
 
     memset(lex_data, 0, sizeof(*lex_data));
     lex_data->macroptr = macro;
-    lex_data->window = window;
+    lex_data->window = WINHELP_GrabWindow(window);
 
     while ((t = yylex()) != EMPTY)
     {
@@ -316,6 +316,7 @@ done:
     for (t = 0; t < lex_data->cache_used; t++)
         HeapFree(GetProcessHeap(), 0, lex_data->cache_string[t]);
     lex_data = prev_lex_data;
+    WINHELP_ReleaseWindow(window);
 
     return ret;
 }
diff --git a/programs/winhlp32/winhelp.c b/programs/winhlp32/winhelp.c
index 8e6ba50..027bf65 100644
--- a/programs/winhlp32/winhelp.c
+++ b/programs/winhlp32/winhelp.c
@@ -500,11 +500,39 @@ static void WINHELP_DeletePageLinks(HLPFILE_PAGE* page)
 
 /***********************************************************************
  *
+ *           WINHELP_GrabWindow
+ */
+WINHELP_WINDOW* WINHELP_GrabWindow(WINHELP_WINDOW* win)
+{
+    WINE_TRACE("Grab %p#%d++\n", win, win->ref_count);
+    win->ref_count++;
+    return win;
+}
+
+/***********************************************************************
+ *
+ *           WINHELP_RelaseWindow
+ */
+BOOL WINHELP_ReleaseWindow(WINHELP_WINDOW* win)
+{
+    WINE_TRACE("Release %p#%d--\n", win, win->ref_count);
+
+    if (!--win->ref_count)
+    {
+        DestroyWindow(win->hMainWnd);
+        return FALSE;
+    }
+    return TRUE;
+}
+
+/***********************************************************************
+ *
  *           WINHELP_DeleteWindow
  */
 static void WINHELP_DeleteWindow(WINHELP_WINDOW* win)
 {
     WINHELP_WINDOW**    w;
+    BOOL bExit;
 
     for (w = &Globals.win_list; *w; w = &(*w)->next)
     {
@@ -514,6 +542,7 @@ static void WINHELP_DeleteWindow(WINHELP_WINDOW* win)
             break;
         }
     }
+    bExit = (Globals.wVersion >= 4 && !lstrcmpi(win->info->name, "main"));
 
     if (Globals.active_win == win)
     {
@@ -537,6 +566,10 @@ static void WINHELP_DeleteWindow(WINHELP_WINDOW* win)
 
     if (win->page) HLPFILE_FreeHlpFile(win->page->file);
     HeapFree(GetProcessHeap(), 0, win);
+
+    if (bExit) MACRO_Exit();
+    if (!Globals.win_list)
+        PostQuitMessage(0);
 }
 
 static char* WINHELP_GetCaption(WINHELP_WNDPAGE* wpage)
@@ -706,9 +739,11 @@ BOOL WINHELP_CreateHelpWindow(WINHELP_WNDPAGE* wpage, int nCmdShow, BOOL remembe
         win->hHandCur = LoadCursorW(0, (LPWSTR)IDC_HAND);
         win->back.index = 0;
         win->font_scale = 1;
+        WINHELP_GrabWindow(win);
     }
     win->page = wpage->page;
     win->info = wpage->wininfo;
+    WINHELP_GrabWindow(win);
 
     if (!bPopup && wpage->page && remember)
     {
@@ -772,6 +807,14 @@ BOOL WINHELP_CreateHelpWindow(WINHELP_WNDPAGE* wpage, int nCmdShow, BOOL remembe
         for (macro = wpage->page->first_macro; macro; macro = macro->next)
             MACRO_ExecuteMacro(win, macro->lpszMacro);
     }
+    /* See #17681, in some cases, the newly created window is closed by the macros it contains
+     * (braindead), so deal with this case
+     */
+    for (win = Globals.win_list; win; win = win->next)
+    {
+        if (!lstrcmpi(win->info->name, wpage->wininfo->name)) break;
+    }
+    if (!win || !WINHELP_ReleaseWindow(win)) return TRUE;
 
     if (bPopup)
     {
@@ -883,7 +926,7 @@ static BOOL WINHELP_HandleTextMouse(WINHELP_WINDOW* win, UINT msg, LPARAM lParam
  */
 static BOOL WINHELP_CheckPopup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* lret)
 {
-    HWND        hPopup;
+    WINHELP_WINDOW*     popup;
 
     if (!Globals.active_popup) return FALSE;
 
@@ -916,9 +959,9 @@ static BOOL WINHELP_CheckPopup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam
     case WM_NCLBUTTONDOWN:
     case WM_NCMBUTTONDOWN:
     case WM_NCRBUTTONDOWN:
-        hPopup = Globals.active_popup->hMainWnd;
+        popup = Globals.active_popup;
         Globals.active_popup = NULL;
-        DestroyWindow(hPopup);
+        WINHELP_ReleaseWindow(popup);
         return TRUE;
     }
     return FALSE;
@@ -1422,7 +1465,8 @@ static LRESULT CALLBACK WINHELP_MainWndProc(HWND hWnd, UINT msg, WPARAM wParam,
                     switch (msgf->msg)
                     {
                     case WM_KEYUP:
-                        if (msgf->wParam == VK_ESCAPE) DestroyWindow(hWnd);
+                        if (msgf->wParam == VK_ESCAPE)
+                            WINHELP_ReleaseWindow((WINHELP_WINDOW*)GetWindowLongPtr(hWnd, 0));
                         break;
                     case WM_RBUTTONDOWN:
                     {
@@ -1486,18 +1530,9 @@ static LRESULT CALLBACK WINHELP_MainWndProc(HWND hWnd, UINT msg, WPARAM wParam,
         CheckMenuItem((HMENU)wParam, MNID_OPTS_FONTS_LARGE,
                       MF_BYCOMMAND | (win->font_scale == 2) ? MF_CHECKED : 0);
         break;
-
-    case WM_NCDESTROY:
-        {
-            BOOL bExit;
-            win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0);
-            bExit = (Globals.wVersion >= 4 && !lstrcmpi(win->info->name, "main"));
-            WINHELP_DeleteWindow(win);
-
-            if (bExit) MACRO_Exit();
-            if (!Globals.win_list)
-                PostQuitMessage(0);
-        }
+    case WM_DESTROY:
+        win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0);
+        WINHELP_DeleteWindow(win);
         break;
     }
     return DefWindowProc(hWnd, msg, wParam, lParam);
diff --git a/programs/winhlp32/winhelp.h b/programs/winhlp32/winhelp.h
index 70e2dc2..e770cb5 100644
--- a/programs/winhlp32/winhelp.h
+++ b/programs/winhlp32/winhelp.h
@@ -71,6 +71,7 @@ typedef struct tagPageSet
 
 typedef struct tagWinHelp
 {
+    unsigned            ref_count;
     WINHELP_BUTTON*     first_button;
     HLPFILE_PAGE*       page;
 
@@ -151,6 +152,8 @@ void WINHELP_DeleteBackSet(WINHELP_WINDOW*);
 HLPFILE* WINHELP_LookupHelpFile(LPCSTR lpszFile);
 HLPFILE_WINDOWINFO* WINHELP_GetWindowInfo(HLPFILE* hlpfile, LPCSTR name);
 void WINHELP_LayoutMainWindow(WINHELP_WINDOW* win);
+WINHELP_WINDOW* WINHELP_GrabWindow(WINHELP_WINDOW*);
+BOOL WINHELP_ReleaseWindow(WINHELP_WINDOW*);
 
 extern const char MAIN_WIN_CLASS_NAME[];
 extern const char BUTTON_BOX_WIN_CLASS_NAME[];





More information about the wine-patches mailing list