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