// // OpenFile // // Opens the file ready for streaming // HRESULT FileReader::OpenFile() { CAutoLockFR rLock (&m_accessLock); // Is the file already opened if (m_hFile != INVALID_HANDLE_VALUE) { //LogDebug("FileReader::OpenFile() file already open"); return NOERROR; } // Has a filename been set yet if (m_pFileName == NULL) { LogDebug("FileReader::OpenFile() no filename"); return ERROR_INVALID_NAME; } WCHAR *pFileName = NULL; DWORD Tmo=14 ; HANDLE hFileUnbuff = INVALID_HANDLE_VALUE; //Can be used to open files in random-access mode to workaround SMB caching problems DWORD accessModeFlags = (m_bUseRandomAccess ? FILE_FLAG_RANDOM_ACCESS : FILE_FLAG_SEQUENTIAL_SCAN); m_bIsStopping = false; pFileName = m_pFileName; //LogDebug("FileReader::OpenFile(), Filename: %ws.", pFileName); do { if (m_bIsStopping) return E_FAIL; if (m_bUseDummyWrites) //enable SMB2/SMB3 file existence cache workaround { if ((wcsstr(pFileName, L".ts.tsbuffer") != NULL)) //timeshift file only { CString tempFileName = pFileName; int replCount = tempFileName.Replace(L".ts.tsbuffer", randomStrGen(12)); if (replCount > 0) { //LogDebug("FileReader::OpenFile(), try to write dummy file to update SMB2 cache - %ws", tempFileName); hFileUnbuff = ::CreateFileW(tempFileName, // The filename (DWORD) (GENERIC_READ | GENERIC_WRITE), // File access (DWORD) (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), // Share access NULL, // Security (DWORD) CREATE_ALWAYS, // Open flags (DWORD) (FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE), // More flags NULL); // Template if (hFileUnbuff != INVALID_HANDLE_VALUE) { char tempData[16] = {0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF}; DWORD bytesWritten; ::WriteFile(hFileUnbuff, tempData, 16, &bytesWritten, NULL); ::CloseHandle(hFileUnbuff); //File is deleted on CloseHandle since FILE_FLAG_DELETE_ON_CLOSE was used hFileUnbuff = INVALID_HANDLE_VALUE; // Invalidate the file //LogDebug("FileReader::OpenFile(), dummy file write %d bytes to %ws", bytesWritten, tempFileName); } } } } // do not try to open a tsbuffer file without SHARE_WRITE so skip this try if we have a buffer file if (wcsstr(pFileName, L".ts.tsbuffer") == NULL) // not tsbuffer files { // Try to open the file in read-only mode (should fail for 'live' recordings) m_hFile = ::CreateFileW(pFileName, // The filename (DWORD) GENERIC_READ, // File access (DWORD) FILE_SHARE_READ, // Share access NULL, // Security (DWORD) OPEN_EXISTING, // Open flags (DWORD) accessModeFlags, // More flags NULL); // Template if (m_hFile != INVALID_HANDLE_VALUE) break ; //This is in case file is being recorded to ('live' recordings) m_hFile = ::CreateFileW(pFileName, // The filename (DWORD) GENERIC_READ, // File access (DWORD) (FILE_SHARE_READ | FILE_SHARE_WRITE), // Share access NULL, // Security (DWORD) OPEN_EXISTING, // Open flags (DWORD) accessModeFlags, // More flags NULL); // Template if (m_hFile != INVALID_HANDLE_VALUE) break ; } else //for tsbuffer files { //This is in case file is being recorded to m_hFile = ::CreateFileW(pFileName, // The filename (DWORD) GENERIC_READ, // File access (DWORD) (FILE_SHARE_READ | FILE_SHARE_WRITE), // Share access NULL, // Security (DWORD) OPEN_EXISTING, // Open flags (DWORD) accessModeFlags, // More flags NULL); // Template if (m_hFile != INVALID_HANDLE_VALUE) break ; } if ((wcsstr(pFileName, L".ts.tsbuffer") != NULL) && (Tmo<10)) //timeshift file only { if (m_bUseDummyWrites) //enable SMB2/SMB3 file existence cache workaround { //Not succeeded in opening file yet, try WRITE_THROUGH dummy file write CString tempFileName = pFileName; int replCount = tempFileName.Replace(L".ts.tsbuffer", randomStrGen(12)); if (replCount > 0) { // LogDebug("FileReader::OpenFile(), try to write dummy file to update SMB2 cache - %ws", tempFileName); hFileUnbuff = ::CreateFileW(tempFileName, // The filename (DWORD) (GENERIC_READ | GENERIC_WRITE), // File access (DWORD) (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), // Share access NULL, // Security (DWORD) CREATE_ALWAYS, // Open flags (DWORD) (FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE | FILE_FLAG_WRITE_THROUGH), // More flags NULL); // Template if (hFileUnbuff != INVALID_HANDLE_VALUE) { char tempData[16] = {0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF}; DWORD bytesWritten; ::WriteFile(hFileUnbuff, tempData, 16, &bytesWritten, NULL); Sleep(50); ::CloseHandle(hFileUnbuff); //File is deleted on CloseHandle since FILE_FLAG_DELETE_ON_CLOSE was used hFileUnbuff = INVALID_HANDLE_VALUE; // Invalidate the file LogDebug("FileReader::OpenFile(), dummy file WRITE_THROUGH write %d bytes to %ws", bytesWritten, tempFileName); } } } //No luck yet, so try unbuffered open and close (to flush SMB2 cache?), //then go round loop again to open it properly (hopefully....) hFileUnbuff = ::CreateFileW(pFileName, // The filename (DWORD) GENERIC_READ, // File access (DWORD) (FILE_SHARE_READ | FILE_SHARE_WRITE), // Share access NULL, // Security (DWORD) OPEN_EXISTING, // Open flags (DWORD) FILE_FLAG_NO_BUFFERING, // More flags NULL); // Template if (hFileUnbuff != INVALID_HANDLE_VALUE) { ::CloseHandle(hFileUnbuff); hFileUnbuff = INVALID_HANDLE_VALUE; // Invalidate the file } //LogDebug("FileReader::OpenFile() unbuff, %d tries to open %ws", 15-Tmo, pFileName); } Sleep(min((20*(15-Tmo)),250)) ; //wait longer between retries as loop iterations increase } while(--Tmo) ; if (Tmo) { if (Tmo<13) // 1 failed + 1 succeded is quasi-normal, more is a bit suspicious ( disk drive too slow or problem ? ) LogDebug("FileReader::OpenFile(), %d tries to succeed opening %ws.", 15-Tmo, pFileName); } else { HRESULT lastErr = HRESULT_FROM_WIN32(GetLastError()); LogDebug("FileReader::OpenFile(), open file failed. Error 0x%x, %ws, filename = %ws", lastErr, HresultToCString(lastErr), pFileName); return E_FAIL; } //LogDebug("FileReader::OpenFile() handle %i %ws", m_hFile, pFileName ); LARGE_INTEGER li; li.QuadPart = 0; ::SetFilePointer(m_hFile, li.LowPart, &li.HighPart, FILE_BEGIN); return S_OK; } // Open
// Main in-game method for Mastermind. void mastermind( istream&in, ostream&out) { char *number = randomStrGen(5); //call to randomStrGen method with default length 5 //Instructions displayed at the start of the game //User must type "begin" to start the game out << "Instructions:" << endl; out << "Welcome to Mastermind! You are a code breaker whose objective is to crack the secret code "; out << "created by Dr. Random. The code is comprised of 5 digits where each digit is between 0-6."; out << "With each guess you make, Dr. Random will respond with helpful clues to aid you in deducing "; out << "the correct code. Good luck, and let the code breaking begin!" << endl; out << "\n\nPlease type begin to begin the game!\n"; //Initialization and declaration of variables string begin; string guess; char playagain; int i=0; int blackPin=0; int whitePin=0; int tries = 0; int track = 0; int guesses=0; char *ARRAY; ARRAY = new char[5]; in >> begin; //gets uers input for start game while( begin != "begin") { out << "Please type begin to begin the game!\n"; in >> begin; } //Checks if user enters begin to start the game if(begin=="begin") { out << "Please enter your first guess: "; in >> guess; strcpy(ARRAY, guess.c_str()); //Loop while guesses are still available while(!in.fail() && guesses < 9) { for(int j=0; j < 5; j++) { track = 1; if(ARRAY[j]==number[j]) { blackPin++; track = 0; } for(int k = 0; k<5; k++) { if(ARRAY[k] == number[j] && k != j && track != 0) { whitePin++; track = 0; } } } if(blackPin==5 && guesses != 9) { guesses=10; whitePin = 0; tries++; } out<<"Correct number and position: " << blackPin << endl; out <<"Correct number, wrong position: " << whitePin <<endl; if(blackPin != 5) { out << "Please enter your next guess: "; in >> guess; tries++; } strcpy(ARRAY, guess.c_str()); guesses++; //if user does guess code if(blackPin==5) { out << "\nGame over!!!"<< endl; out << "It took you " << tries << " tries to guess the correct combination: "; for(int i=0; i<5; i++) { out << number[i]; } //if user wants to play again... out << '\n'; out << "To play again type y, or type n to quit: "; in >> playagain; if(playagain == 'y' || playagain == 'Y') { //reset guesses and tries guesses = 0; tries = 0; //new random numbers number = randomStrGen(5); out << "Please enter your first guess: "; in >> guess; strcpy(ARRAY, guess.c_str()); }