void AFNI_start_fetching_url( char *urlstring ) { pid_t child_pid ; #ifdef CYGWIN /* 18 Dec 2002 */ FAIL_MESSAGE("not possible under Cygwin") ; return ; #else /*-- decide if we are to do anything --*/ if( ! AFNI_yesenv("AFNI_VERSION_CHECK") ){ /* never check */ FAIL_MESSAGE("AFNI_VERSION_CHECK forbids") ; return ; } #undef VDELAY #define VDELAY 1234567 /* about 2 weeks */ /* check if we did this in the last VDELAY seconds */ /* also, update global motd_old */ if( vc_check_too_soon() ) { disabled = 1 ; return ; } /*-- OK, start the child process --*/ child_pid = fork() ; if( child_pid == (pid_t)(-1) ){ /* bad */ FAIL_MESSAGE("can't fork") ; return ; } /*---------------------------------------------------------*/ if( child_pid > 0 ){ /* I'm the parent */ /*-- save PID of child for later use --*/ vc_child_pid = child_pid ; /*-- open an IOCHAN to talk to child --*/ vc_ioc = iochan_init( STR_CHILD , "accept" ) ; if( vc_ioc == NULL ){ kill(child_pid,SIGTERM) ; /* cf. Abraham and Isaac */ vc_child_pid = (pid_t)(-1) ; FAIL_MESSAGE("can't open connection to child") ; } else { atexit( vc_exit ) ; /* 12 Dec 2002 */ } return ; /*---------------------------------------------------------*/ } else { /* I'm the child */ /* (never returns) */ int nbuf=0 , jj ; char *vbuf=NULL ; IOCHAN *ioc ; struct utsname ubuf ; char ua[512] ; iochan_enable_perror(0) ; /* don't print TCP/IP error messages */ signal( SIGTERM , vexit ) ; /* if parent kills us, call vexit() */ /*-- get information from the AFNI server --*/ #define USE_HTTP_10 #ifdef USE_HTTP_10 # undef PCLAB # ifdef SHOWOFF # undef SHSH # undef SHSHSH # define SHSH(x) #x # define SHSHSH(x) SHSH(x) # define PCLAB SHSHSH(SHOWOFF) # else # define PCLAB "Unknown" # endif #endif /** 25 Mar 2005: send more info in the request header **/ #ifdef USE_HTTP_10 ubuf.nodename[0] = ubuf.sysname[0] = ubuf.machine[0] = '\0' ; jj = uname( &ubuf ) ; if( jj >= 0 && ubuf.nodename[0] != '\0' ) sprintf( ua , "afni (avers='%s'; prec='%s' node='%s'; sys='%s'; mach='%s')" , AVERZHN, PCLAB, ubuf.nodename, ubuf.sysname, ubuf.machine ) ; else sprintf( ua , "afni (avers='%s'; prec='%s')" , AVERZHN , PCLAB ) ; set_HTTP_10( 1 ) ; set_HTTP_user_agent( ua ) ; #else set_HTTP_10( 0 ) ; #endif /* send the request */ THD_death_setup( 34567 ) ; /* die if 34.567 seconds passes away */ nbuf = read_URL( urlstring , &vbuf ) ; /* may take a while */ set_HTTP_10( 0 ) ; /*-- if this failed, quit --*/ if( nbuf <= 0 || vbuf == NULL || vbuf[0] == '\0' ) { /* block recheck until a new DELAY has passed 22 Mar 2016 [rickr] */ /* - also so server is not flooded when there are issues */ AFNI_update_vctime(NULL, NULL); vexit(1); } /*-- talk to parent process thru IOCHAN --*/ ioc = iochan_init( STR_CHILD , "create" ) ; if( ioc == NULL ) vexit(2); /*-- wait until ioc is ready for writing --*/ jj = iochan_writecheck(ioc,-1) ; if( jj < 0 ) vexit(3); /*-- send the info in vbuf --*/ iochan_sendall( ioc , vbuf , nbuf ) ; while( ! iochan_clearcheck(ioc,10) ) /* loop until cleared */ AFNI_sleep(10) ; /* by parent process */ AFNI_sleep(10); /* a little extra napping, then death */ _exit(0); } #endif /* not CYGWIN */ }
int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow) { HANDLE hSingleInstanceMutex; // Filename and path buffers. TCHAR *exe_path = NULL; // MAX_PATH #define EXE_PATH_LEN (MAX_PATH) TCHAR *dll_filename = NULL; // MAX_PATH+32 #define DLL_FILENAME_LEN (MAX_PATH+32) TCHAR *last_backslash; HKEY hkeyCLSID = NULL; // HKEY_CLASSES_ROOT\\CLSID DWORD exe_path_len; LONG lResult; unsigned int i; static const TCHAR prg_title[] = _T("ROM Properties Page Configuration"); RP_UNUSED(hPrevInstance); // Set Win32 security options. secoptions_init(); // Check if another instance of rp-config is already running. // References: // - https://stackoverflow.com/questions/4191465/how-to-run-only-one-instance-of-application // - https://stackoverflow.com/a/33531179 // TODO: Localized window title? hSingleInstanceMutex = CreateMutex(nullptr, TRUE, _T("Local\\com.gerbilsoft.rom-properties.rp-config")); if (!hSingleInstanceMutex || GetLastError() == ERROR_ALREADY_EXISTS) { // Mutex already exists. // Set focus to the existing instance. // TODO: Localized window titles? HWND hWnd = FindWindow(_T("#32770"), prg_title); if (hWnd) { SetForegroundWindow(hWnd); } return EXIT_SUCCESS; } // Set the C locale. // TODO: C++ locale? setlocale(LC_ALL, ""); #define FAIL_MESSAGE(msg) do { \ MessageBox(NULL, (msg), prg_title, MB_ICONSTOP); \ goto fail; \ } while (0) // Get the executable path. // TODO: Support longer than MAX_PATH? exe_path = malloc(MAX_PATH*sizeof(TCHAR)); if (!exe_path) FAIL_MESSAGE(_T("Failed to allocate memory for the EXE path.")); exe_path_len = GetModuleFileName(hInstance, exe_path, EXE_PATH_LEN); if (exe_path_len == 0 || exe_path_len >= EXE_PATH_LEN) FAIL_MESSAGE(_T("Failed to get the EXE path.")); // Find the last backslash. last_backslash = _tcsrchr(exe_path, L'\\'); if (last_backslash) { // NULL out everything after the backslash. last_backslash[1] = 0; exe_path_len = (DWORD)(last_backslash - exe_path + 1); } else { // Invalid path... // FIXME: Handle this. FAIL_MESSAGE(_T("EXE path is invalid.")); } // Initialize dll_filename with exe_path. dll_filename = malloc(DLL_FILENAME_LEN*sizeof(TCHAR)); if (!dll_filename) FAIL_MESSAGE(_T("Failed to allocate memory for the DLL filename.")); memcpy(dll_filename, exe_path, exe_path_len*sizeof(TCHAR)); // First, check for rom-properties.dll in rp-config.exe's directory. _tcscpy(&dll_filename[exe_path_len], _T("rom-properties.dll")); TRY_LOAD_DLL(dll_filename); // Check the architecture-specific subdirectory. _tcscpy(&dll_filename[exe_path_len], rp_subdir); // NOTE: -1 because _countof() includes the NULL terminator. _tcscpy(&dll_filename[exe_path_len + _countof(rp_subdir) - 1], _T("rom-properties.dll")); TRY_LOAD_DLL(dll_filename); // Check the CLSIDs. lResult = RegOpenKeyEx(HKEY_CLASSES_ROOT, _T("CLSID"), 0, KEY_ENUMERATE_SUB_KEYS, &hkeyCLSID); if (lResult != ERROR_SUCCESS) FAIL_MESSAGE(_T("Failed to open HKEY_CLASSES_ROOT\\CLSID.")); // Need to open "HKCR\\CLSID\\{CLSID}\\InprocServer32". for (i = 0; i < _countof(CLSIDs); i++) { HKEY hkeyClass, hkeyInprocServer32; DWORD cbData, dwType; lResult = RegOpenKeyEx(hkeyCLSID, CLSIDs[i], 0, KEY_ENUMERATE_SUB_KEYS, &hkeyClass); if (lResult != ERROR_SUCCESS) continue; lResult = RegOpenKeyEx(hkeyClass, _T("InprocServer32"), 0, KEY_READ, &hkeyInprocServer32); if (lResult != ERROR_SUCCESS) { RegCloseKey(hkeyClass); continue; } // Read the default value to get the DLL filename. cbData = DLL_FILENAME_LEN*sizeof(TCHAR); lResult = RegQueryValueEx( hkeyInprocServer32, // hKey NULL, // lpValueName NULL, // lpReserved &dwType, // lpType (LPBYTE)dll_filename, // lpData &cbData); // lpcbData RegCloseKey(hkeyInprocServer32); RegCloseKey(hkeyClass); if (lResult != ERROR_SUCCESS || (dwType != REG_SZ && dwType != REG_EXPAND_SZ)) continue; // Verify the NULL terminator. if ((cbData % sizeof(TCHAR) != 0) || dll_filename[(cbData/sizeof(TCHAR))-1] != 0) { // Either this isn't a multiple of 2 bytes, // or there's no NULL terminator. continue; } if (dll_filename[0] != 0 && dwType == REG_EXPAND_SZ) { // Expand the string. // cchExpand includes the NULL terminator. TCHAR *wbuf; DWORD cchExpand = ExpandEnvironmentStrings(dll_filename, nullptr, 0); if (cchExpand == 0) { // Error expanding the string. continue; } wbuf = malloc(cchExpand*sizeof(TCHAR)); cchExpand = ExpandEnvironmentStrings(dll_filename, wbuf, cchExpand); if (cchExpand == 0) { // Error expanding the string. free(wbuf); } else { // String has been expanded. free(dll_filename); dll_filename = wbuf; } } // Attempt to load this DLL. TRY_LOAD_DLL(dll_filename); } // All options have failed... MessageBox(NULL, _T("Could not find rom-properties.dll.\n\n") _T("Please ensure the DLL is present in the same\ndirectory as rp-config.exe."), prg_title, MB_ICONWARNING); fail: free(exe_path); free(dll_filename); if (hkeyCLSID) { RegCloseKey(hkeyCLSID); } return EXIT_FAILURE; }