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