xref: /trunk/main/migrationanalysis/src/msokill/msokill.cpp (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb) !
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 /*
29  * Description: Put MSO in a state where it can be closed using
30  *              automation or kill it completely
31  */
32 
33 #include "stdafx.h"
34 #include <stdio.h>
35 
36 
37 void KillOffice();
38 BOOL KillAppFromWindow(HWND hWnd, char *appName);
39 BOOL CloseActiveDialogs();
40 void printUsage();
41 
42 //Callbacks used in closing
43 BOOL CALLBACK CloseOfficeDlgProc(HWND hwndChild, LPARAM lParam);
44 BOOL CALLBACK CountOfficeDlgProc(HWND hwndChild, LPARAM lParam);
45 
46 //Global counters for number of windows found
47 int gWDDlgCount = 0;
48 int gXLDlgCount = 0;
49 int gPPDlgCount = 0;
50 
51 //Dialog window class names for excel, powerpoint and word
52 //These are "Best guess" dialog names
53 const char *pWordDlg2k  = "bosa_sdm_Microsoft Word 9.0";
54 const char *pWordDlg2k3 = "bosa_sdm_Microsoft Office Word";
55 const char *pXLDlg2k    = "bosa_sdm_XL9";
56 const char *pPPDlg2k    = "#32770";
57 const char *pXLDlg2k3   = "bosa_sdm_XL9";
58 const char *pPPDlg2k3   = "#32770";
59 const char *pGenMSODlg  = "bosa_sdm_Mso96";
60 //consider adding - bosa_sdm_Mso96
61 
62 //Command Line Argument constants
63 const char *ARG_HELP  = "--help";
64 const char *ARG_KILL  = "--kill";
65 const char *ARG_CLOSE = "--close";
66 
67 //Window class names for MSO apps - if we need to look at other office instances
68 //then this list would need to be expanded
69 #define NUM_WINDOWCLASSNAMES 4
70 char *wndClassName[NUM_WINDOWCLASSNAMES] = {"OpusApp", "XLMAIN", "PP9FrameClass", "PP10FrameClass"};
71 
72 int main(int argc, char* argv[])
73 {
74     if (argc < 2) {
75         printUsage();
76         return 0;
77     }
78 
79     if (strcmpi(argv[1], ARG_HELP) == 0) {
80         printUsage();
81         return 0;
82     }
83 
84     if (strcmpi(argv[1], ARG_KILL) == 0) {
85         KillOffice();
86         return 0;
87     }
88 
89     if (strcmpi(argv[1], ARG_CLOSE) == 0) {
90         CloseActiveDialogs();
91         return 0;
92     }
93 
94     return 0;
95 }
96 
97 /*--------------------------------------------------------------
98   Find the MSO window if it is available and explictly kill it
99   MSO apps in this case are Excel, Word and PP
100   Use FindWindow Win32 API to detect if they are available
101 
102   -------------------------------------------------------------*/
103 void KillOffice() {
104     HWND hWnd;
105 
106     for (int i=0;i<NUM_WINDOWCLASSNAMES;i++) {
107         int j = 0;
108         while (((hWnd = FindWindow(wndClassName[i], NULL )) != NULL) && (j < 10)) {
109             KillAppFromWindow(hWnd, wndClassName[i]);
110             j++;
111         }
112     }
113 }
114 
115 /*--------------------------------------------------------------
116   Using window handle, get process handle and try to kill the
117   app. This may not be successful if you do not have enough
118   privileges to kill the app.
119 
120   --------------------------------------------------------------*/
121 BOOL KillAppFromWindow(
122     HWND hWnd,
123     char *
124 #ifdef _DEBUG
125     appName
126 #endif
127 )
128 {
129     BOOL bRet = TRUE;
130 
131     if(hWnd == NULL) {
132         //The app doesn't appear to be running
133 #ifdef _DEBUG
134         printf("App %s: window not found.\n,", appName);
135 #endif
136         bRet = FALSE;
137     } else {
138         DWORD pid;  // Variable to hold the process ID.
139         DWORD dThread;  // Variable to hold (unused) thread ID.
140         dThread = GetWindowThreadProcessId(hWnd, &pid);
141         HANDLE hProcess; // Handle to existing process
142 
143         hProcess = OpenProcess(SYNCHRONIZE | PROCESS_ALL_ACCESS, TRUE, pid);
144         if (hProcess == NULL) {
145 #ifdef _DEBUG
146             printf("App %s : Failed to get process handle",appName);
147 #endif
148             bRet = FALSE;
149         } else {
150             if (!TerminateProcess(hProcess, 0)) {
151                 LPTSTR lpMsgBuf;
152                 FormatMessage(
153                     FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
154                     NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
155                     (LPTSTR) &lpMsgBuf, 0, NULL );
156                 printf("%s\n", lpMsgBuf);
157                 LocalFree( lpMsgBuf );
158                 bRet = FALSE;
159             }
160 #ifdef _DEBUG
161             else {
162                 printf("Kill %s appears to be successful.\n", appName);
163             }
164 #endif
165         }
166     }
167     return bRet;
168 }
169 
170 /*--------------------------------------------------------------
171   Close the dialogs if possible based on their window class
172   Use the EnumChildWindows win32 api for this
173   --------------------------------------------------------------*/
174 BOOL CloseActiveDialogs() {
175     char buff[1024];
176 
177     gWDDlgCount = 0;
178     gXLDlgCount = 0;
179     gPPDlgCount = 0;
180 
181     EnumChildWindows(GetDesktopWindow(), CloseOfficeDlgProc, (LPARAM) 0);
182     sprintf(buff, "Word: %d\tExcel: %d\tPP: %d", gWDDlgCount, gXLDlgCount, gPPDlgCount);
183     return TRUE;
184 }
185 
186 /*--------------------------------------------------------------
187   Callback for EnumChildWindows that sends close message to
188   any dialogs that match window class of MSO dialogs
189 
190   --------------------------------------------------------------*/
191 BOOL CALLBACK CloseOfficeDlgProc(HWND hwndChild, LPARAM)
192 {
193     //bosa_sdm_Microsoft Word 9.0
194     //bosa_sdm_XL9
195     //#32770 (Dialog)
196 
197     char szBuff[4096];
198     if (GetClassName(hwndChild, szBuff, 4096) == 0) {
199 
200     } else {
201         if ((strcmpi(szBuff, pWordDlg2k) == 0) || (strcmpi(szBuff, pWordDlg2k3) == 0)) {
202             gWDDlgCount++;
203             SendMessage(hwndChild, WM_CLOSE, 0, 0);
204         }
205         if (strcmpi(szBuff, pXLDlg2k) == 0) {
206             gXLDlgCount++;
207             SendMessage(hwndChild, WM_CLOSE, 0, 0);
208         }
209         if (strcmpi(szBuff, pPPDlg2k) == 0) {
210             gPPDlgCount++;
211             SendMessage(hwndChild, WM_CLOSE, 0, 0);
212         }
213         if (strcmpi(szBuff, pGenMSODlg) == 0) {
214             SendMessage(hwndChild, WM_CLOSE, 0, 0);
215         }
216     }
217 
218     return TRUE;
219 }
220 
221 
222 /*--------------------------------------------------------------
223   Callback for EnumChildWindows that counts numnnber of
224   dialogs that match window class of MSO dialogs
225 
226   --------------------------------------------------------------*/
227 BOOL CALLBACK CountOfficeDlgProc(HWND hwndChild, LPARAM)
228 {
229     char szBuff[4096];
230     if (GetClassName(hwndChild, szBuff, 4096) == 0) {
231 
232     } else {
233         if ((strcmpi(szBuff, pWordDlg2k) == 0) || (strcmpi(szBuff, pWordDlg2k3) == 0)) {
234             gWDDlgCount++;
235         }
236         if (strcmpi(szBuff, pXLDlg2k) == 0) {
237             gXLDlgCount++;
238         }
239         if (strcmpi(szBuff, pPPDlg2k) == 0) {
240             gPPDlgCount++;
241         }
242     }
243 
244     return TRUE;
245 }
246 
247 /*--------------------------------------------------------------
248   Simple usage message...
249 
250   -------------------------------------------------------------*/
251 void printUsage() {
252     printf("Recovery Assistant Utility - try and put MSO apps in a recoverable state\n");
253     printf("Copyright Sun Microsystems 2008\n");
254     printf("Options:\n");
255     printf("   --help : This message\n");
256     printf("   --close: Attempt to close any open dialogs owned by \n");
257     printf("            MSO apps so Application.Quit() can succeed\n");
258     printf("   --kill : Kill any open MSO apps. Use with caution and only as a last resort\n\n");
259 }