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 }