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