/*** Main source of the Gotcha! screencapture program. Copyright (C) 1998-2002 Thorsten Thielen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***/ #define INCL_WINHOOKS #include "gotcha.h" #include "dll/gotchdll.h" #include "settings.h" #include "string.h" #include "io.h" #define INCL_EXCEPTQ_CLASS #define INCL_LOADEXCEPTQ #include "exceptq.h" HAB hab; HWND hwndFrame, hwndSnapshot; PFNWP OldFrameWP, wpOldButton; PSETTINGS pset; BOOL g_fIdle = FALSE, g_fSetPathName = FALSE; HWND g_hwndMenuSSW; HMODULE g_hmod = NULLHANDLE; Helper *g_phelp = NULL; BOOL g_usePMps = FALSE; CHAR g_installerSavePath[_MAX_PATH] = {0}; BOOL g_installer = FALSE; CHAR g_installerINI[_MAX_PATH] = {0}; #include "bitmap.cpp" #include "mainwin.cpp" #include "snapshot.cpp" #include "savebmp.cpp" // ** CheckCmdlineArgs **************************************************** /*FOLD00*/ BOOL CheckCmdlineArgs (int argc, char *argv[]) { BOOL fAuto = FALSE; for (USHORT i = 1; i < argc; i++) { #ifndef _QUIET_ // batch mode if ((stricmp (argv[i], "-a") == 0)) { if (pset->QuerySaveStyle () != FSS_FORCEFILE) pset->SetFileSaveStyle (FSS_NUMFILES); fAuto = TRUE; if (i < argc-1) if (argv[i+1][0] != '-') { i++; pset->SetFileSaveStyle (FSS_NUMFILES); pset->SetNumSaveDir (argv[i]); } } // force saving to the given file name else if ((stricmp (argv[i], "-f") == 0) && (i < argc-1)) { if (argv[i+1][0] != '-') { i++; pset->SetFileSaveStyle (FSS_FORCEFILE); pset->SetForceSaveFile (argv[i]); g_fSetPathName = TRUE; } } // set to idle priority else if (stricmp (argv[i], "-i") == 0) { g_fIdle = TRUE; pset->SetFlag (SEI_IDLEPRIORITY, TRUE); } #else // use default PM print screen if (stricmp (argv[i], "-p") == 0) { g_usePMps = TRUE; } if (stricmp (argv[i], "-i") == 0 || stricmp (argv[i], "-i+") == 0) { CHAR * memdrv = getenv("MEMDRIVE"); g_installer = TRUE; if (memdrv) { strcpy(g_installerSavePath, memdrv); strcat(g_installerSavePath, ":\\"); } else strcpy(g_installerSavePath, "Z:\\"); if (stricmp (argv[i], "-i+") == 0) strcpy(g_installerINI, "gotchaq.ini"); else { strcpy(g_installerINI, g_installerSavePath); strcat(g_installerINI, "gotchaq.ini"); } } #endif } return fAuto; } // ** main **************************************************************** /*FOLD00*/ int main (int argc, PSZ argv[]) { ScopedExceptqLoader sel; #ifdef _DOLOGDEBUG_ LogDebug( "Gotcha! start" ); #endif #ifdef _DOLOGMEM_ LogMem("main", TRUE); #endif // init system and msg queue hab = WinInitialize (0); HMQ hmq = WinCreateMsgQueue (hab, 0); int rc; #ifdef _QUIET_ //Needed here for setting adjustments for installer version CheckCmdlineArgs (argc, argv); #endif // Load settings moved up here so the string table is available for the already running error pset = new SETTINGS; pset->idleSetInIni = pset->QueryFlag(SEI_IDLEPRIORITY); pset->saveStyle = pset->QuerySaveStyle (); pset->pNumSaveDir = pset->QueryNumSaveDir (); pset->pForceSaveFile = pset->QueryForceSaveFile(); pset->bSerialCapture = pset->SerialCapture (); //Reset Save style and directory for installer #ifdef _QUIET_ if ((Version() < 2)) { if (! g_installer) DisplayError(RSTR (IDS_ERROR_DLLOUTDATED), RSTR (IDS_ERROR_DLLOUTDATEDMSG)); exit (0); } HMTX hmtx = NULLHANDLE; // running multiple instances orphans all but the first hook unloaded rc = DosOpenMutexSem("\\SEM32\\GOTCHA", &hmtx); if (!rc) { if (! g_installer) DisplayError(RSTR (IDS_ERROR_ALREADYRUNNING), RSTR (IDS_ERROR_ALREADYRUNNINGMSG)); exit (0); } rc = DosCreateMutexSem("\\SEM32\\GOTCHA", &hmtx, 0, FALSE); if (rc) { if (! g_installer) DisplayError(RSTR (IDS_ERROR_SEMAPHOREFAILED), RSTR (IDS_ERROR_SEMAPHOREFAILEDMSG)); exit (0); } #endif // register our window classes WinRegisterClass (hab, "thth.wc.gotcha.main", WindowProcedure, 0L, sizeof (ULONG)*2L); #ifndef _QUIET_ WinRegisterClass (hab, "thth.wc.gotcha.snapshot", wpSnapshot, CS_SIZEREDRAW, sizeof (ULONG)*2L); // check cmd line args and if "-a" found take screenshot and exit if (CheckCmdlineArgs (argc, argv)) { CaptureWindow (HWND_DESKTOP, HWND_DESKTOP, NULL, TRUE); pset->SetFileSaveStyle(pset->saveStyle); pset->SetNumSaveDir (pset->pNumSaveDir); delete pset; WinDestroyMsgQueue (hmq); WinTerminate (hab); exit (0); } #endif SetIdlePriority(pset->QueryFlag(SEI_IDLEPRIORITY)); // create the windows hwndFrame = CreateMainWindow (); #ifndef _QUIET_ hwndSnapshot = CreateSnapshotWindow (); SWP swp; USHORT us[7]; // position main window pset->QueryWindowData (&swp, us, FALSE); WinSetWindowPos (hwndFrame, HWND_DESKTOP, swp.x,swp.y, 0,0, SWP_SHOW | SWP_MOVE); #endif #ifdef _QUIET_ bool fPrtScr = FALSE; if (!g_usePMps) { // always turn it off while running // WinSet does not effect the ini setting WinSetSysValue(HWND_DESKTOP, SV_PRINTSCREEN , fPrtScr); } InitDLL (hab, hwndFrame, g_usePMps); StartInputHook (); #endif #ifndef _QUIET_ // position snapshot window pset->QueryWindowData (&swp, us); // size, activate & show window WinSetWindowPos (hwndSnapshot, HWND_DESKTOP, swp.x,swp.y, swp.cx,swp.cy, SWP_SHOW | SWP_SIZE | SWP_MOVE); if (! pset->SnapshotWindow ()) WinShowWindow (hwndSnapshot, FALSE); else WinShowWindow (hwndSnapshot, TRUE); WinSetWindowPos (hwndFrame, NULLHANDLE, 0,0, 0,0, SWP_SHOW); WinSetWindowPos (WinWindowFromID (hwndFrame, FID_CLIENT), NULLHANDLE, 0,0, 0,0, SWP_SHOW); #endif g_phelp = new Helper(hwndFrame); // do the main msg loop QMSG qmsg; while (WinGetMsg (hab, &qmsg, 0L, 0, 0)) WinDispatchMsg (hab, &qmsg); // Set priorty to unless user set regular since running -q sets it to idle in the ini if (g_fIdle) { pset->SetFlag (SEI_IDLEPRIORITY, pset->idleSetInIni); } // Don't change the ini stored paths if the paths were set from the command line if (g_fSetPathName) { pset->SetFileSaveStyle(pset->saveStyle); pset->SetForceSaveFile (pset->pForceSaveFile); pset->SetNumSaveDir (pset->pNumSaveDir); } #ifndef _QUIET_ // save size, etc. of snapshot window WinQueryWindowPos (hwndSnapshot, &swp); pset->SetWindowData (&swp); // save size, etc. of main window WinQueryWindowPos (hwndFrame, &swp); pset->SetWindowData (&swp, FALSE); #endif // goodbye windows! #ifndef _QUIET_ WinDestroyWindow (hwndSnapshot); #endif WinDestroyWindow (hwndFrame); #ifdef _QUIET_ // Reset to user PM print screen choice if (!g_usePMps) { ULONG ulDataSize = 0; rc = PrfQueryProfileSize(HINI_USERPROFILE, "PM_ControlPanel", "PrintScreen", &ulDataSize ); rc = PrfQueryProfileData(HINI_USERPROFILE, "PM_ControlPanel", "PrintScreen", &fPrtScr, &ulDataSize); if (!rc) // Print screen is on by default (no ini entry) fPrtScr = TRUE; WinSetSysValue(HWND_DESKTOP, SV_PRINTSCREEN , fPrtScr); } StopInputHook (); DosCloseMutexSem(hmtx); #endif delete g_phelp; delete pset; WinDestroyMsgQueue (hmq); WinTerminate (hab); #ifdef _DOLOGMEM_ LogMem("main", FALSE); #endif #ifdef _DOLOGDEBUG_ LogDebug( "Gotcha! end" ); #endif } // ** DisplayError ******************************************************** /*FOLD00*/ VOID DisplayError (PSZ pszTitle, PSZ psz, ...) { CHAR dstring[401]; va_list valst; va_start (valst, psz); vsnprintf (dstring, 401, psz, valst); va_end (valst); WinMessageBox (HWND_DESKTOP, WinQueryActiveWindow (HWND_DESKTOP), dstring, pszTitle, 0, MB_OK | MB_ERROR | MB_APPLMODAL | MB_MOVEABLE); } #if 0 // saymsg2 was adapted from code in FM/2 APIRET saymsg2(int DefaultButton, HWND hwnd, PCSZ pszTitle, PCSZ pszFmt, ...) { ULONG i; APIRET rc; CHAR szMsg[4096]; va_list va; MB2INFO *pmbInfo; MB2D mb2dBut[3]; ULONG ulInfoSize = (sizeof(MB2INFO) + (sizeof(MB2D) * 2)); va_start(va, pszFmt); szMsg[sizeof(szMsg) - 1] = 0; vsprintf(szMsg, pszFmt, va); va_end(va); if (szMsg[sizeof(szMsg) - 1]) { fprintf(stderr, "Buffer overflow in saymsg2 - need %u bytes\n", strlen(szMsg) + 1); fflush(stderr); } memset(mb2dBut, 0, sizeof(MB2D) * 2); strcpy(mb2dBut[0].achText,RSTR(IDS_OK)); strcpy(mb2dBut[1].achText,RSTR(IDS_CANCEL)); //strcpy(mb2dBut[2].achText,RSTR(IDS_SETTINGS)); mb2dBut[0].idButton = 1; mb2dBut[1].idButton = 2; //mb2dBut[2].idButton = 3; if (DefaultButton) mb2dBut[DefaultButton - 1].flStyle = BS_DEFAULT; pmbInfo = (MB2INFO *) malloc(ulInfoSize); memset(pmbInfo, 0, ulInfoSize); if (pmbInfo) { pmbInfo->cb = ulInfoSize; pmbInfo->hIcon = 0; pmbInfo->cButtons = 2; pmbInfo->flStyle = MB_MOVEABLE | MB_ICONQUESTION ; pmbInfo->hwndNotify = NULLHANDLE; for (i = 0; i < 2; i++) { memcpy( pmbInfo->mb2d+i , mb2dBut+i , sizeof(MB2D)); } rc = WinMessageBox2(HWND_DESKTOP, hwnd, szMsg, pszTitle, SM2_DIALOG, pmbInfo); WinSetFocus(HWND_DESKTOP, SM2_DIALOG); free(pmbInfo); return rc; } return MBID_ERROR; } #endif // ** AddSysMenuItem ****************************************************** /*FOLD00*/ VOID AddSysMenuItem (HWND hwndFrame, MENUITEM *Item, PSZ Text) { HWND hwndSysMenu = WinWindowFromID (hwndFrame, FID_SYSMENU); USHORT idSysMenu = SHORT1FROMMR (WinSendMsg (hwndSysMenu, MM_ITEMIDFROMPOSITION, NULL, NULL )); MENUITEM miSysMenu; WinSendMsg (hwndSysMenu, MM_QUERYITEM, MPFROM2SHORT (idSysMenu,FALSE), MPFROMP(&miSysMenu)); HWND hwndSysSubMenu = miSysMenu.hwndSubMenu; WinSendMsg (hwndSysSubMenu, MM_INSERTITEM, MPFROMP(Item), MPFROMP(Text)); } // ** DoCountdown ********************************************************* /*fold00*/ VOID DoCountdown (ULONG ul) { if (ul > 10) DosBeep (4000L-3000L, 20); else DosBeep (4000L-ul*300L, 20); } // ** SetIdlePriority **************************************************** /*FOLD00*/ VOID SetIdlePriority (BOOL f) { #ifndef _QUEIT_ if (f) DosSetPriority(PRTYS_PROCESS, PRTYC_IDLETIME, 0, 0); else DosSetPriority(PRTYS_PROCESS, PRTYC_REGULAR, 0, 0); #else DosSetPriority(PRTYS_PROCESS, PRTYC_FOREGROUNDSERVER, 0, 0); #endif } // *********************************************************************** #ifdef _DOLOGMEM_ VOID LogMem (PSZ psz, BOOL f) { FILE *pf = fopen("gotcha.mem","ab"); static ULONG TotalPhysicalMemory, ul = 0; ULONG i; if (!f) ul--; DosQuerySysInfo(QSV_TOTAVAILMEM, QSV_TOTAVAILMEM, &TotalPhysicalMemory, sizeof(TotalPhysicalMemory)); for (i = 0; i < ul; i++) fputs(" ", pf); fprintf(pf,"%10ld (%s)\n", TotalPhysicalMemory, psz); if (f) ul++; fclose(pf); } #endif #ifdef _DOLOGDEBUG_ VOID LogDebug( PSZ psz, ... ) { CHAR dstring[401]; va_list valst; va_start (valst, psz); vsnprintf (dstring, 401, psz, valst); va_end (valst); FILE *pf = fopen( "gotcha.log", "ab" ); fprintf( pf, "%s\n", dstring ); fclose( pf ); } #endif // ***********************************************************************