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 }