/*******************************************************//** * Gets module folder path. * * @param [in,out] szDir If non-null, the dir. *******************************************************/ void MainController::getModuleFolderPath(_TCHAR * szDir) { //allocate string buffers using character independent data type. _TCHAR exePath[MAX_PATH] = _T(""); GetModuleFileName(NULL, exePath, MAX_PATH); char ch = '\\'; _TCHAR * slashAndFileName = _tcsrchr(exePath, ch); size_t theSize = slashAndFileName - exePath; // Extract directory _tcsnccpy_s(szDir, MAX_PATH, exePath, theSize); szDir[theSize] = '\0'; }
LPTSTR Error2String( DWORD dwError ) { static TCHAR szUserBuf[512]; static LPTSTR szErrorMsg = _T( "internal error" ); LPTSTR lpMsgBuf = NULL; DWORD dwLength; dwLength = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), ( LPTSTR ) & lpMsgBuf, 0, NULL ); if( dwLength == 0 ) { lpMsgBuf = _T( "internal error" ); } _tcsnccpy_s( szUserBuf, _countof( szUserBuf ), lpMsgBuf, _tcslen( lpMsgBuf ) ); LocalFree( lpMsgBuf ); return szUserBuf; }
LONG GetJobNumber (PROCESS_INFORMATION *pProcessInfo, LPCTSTR Command) /* Create a job number for the new process, and enter the new process information into the job database. */ /* The job database is maintained in a shared file in the C:\temp directory. The name is a combination of the user name and ".JobMgt". The file is created at the time of the first job and deleted when the last job is killed. This file is shared by all the job management functions. The file is assumed to be "small" (< 4 GB). If the file is large, the code will fail in several places, but there is protection to limit the number of jobs (arbitrarily, but not unreasonably) to 10000 (MAX_JOBS_ALLOWED). Return -1 in case of failure. */ { HANDLE hJobData, hProcess; JM_JOB jobRecord; DWORD jobNumber = 0, nXfer, exitCode; LARGE_INTEGER fileSize, fileSizePlus; TCHAR jobMgtFileName[MAX_PATH]; OVERLAPPED regionStart; if (!GetJobMgtFileName (jobMgtFileName)) return -1; hJobData = CreateFile (jobMgtFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hJobData == INVALID_HANDLE_VALUE) { ReportError (_T ("Failed to open Job DB."), 0, TRUE); return -1; } /* Lock the entire file plus one record for exclusive access as we will be making a new entry. Note how it is necessary (and possible!) to lock beyond the current end of file. Doing so prevents concurrent attempts to add a new record at the end of the file. */ regionStart.Offset = 0; regionStart.OffsetHigh = 0; regionStart.hEvent = (HANDLE)0; GetFileSizeEx (hJobData, &fileSize); fileSizePlus.QuadPart = fileSize.QuadPart + SJM_JOB; LockFileEx (hJobData, LOCKFILE_EXCLUSIVE_LOCK, 0, fileSizePlus.LowPart, fileSizePlus.HighPart, ®ionStart); __try { /* Assure that the region is unlocked. */ /* Read records to find empty slot (corresponding to the job number). Extend the file to create a new job number if required. */ /* See text comments and Exercise 6-8 regarding a potential defect (and fix) caused by process ID reuse. */ while (jobNumber < MAX_JOBS_ALLOWED && ReadFile (hJobData, &jobRecord, SJM_JOB, &nXfer, NULL) && (nXfer > 0)) { if (jobRecord.ProcessId == 0) break; /* Also use this slot if corresponding job has ended. */ hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, jobRecord.ProcessId); if (hProcess == NULL) break; if (GetExitCodeProcess (hProcess, &exitCode) && CloseHandle (hProcess) && (exitCode != STILL_ACTIVE)) break; jobNumber++; } /* Either an empty slot has been found, or we are at end of the file and need to create a new one, or we've exceeded the max number of jobs. */ if (jobNumber >= MAX_JOBS_ALLOWED) return -1; if (nXfer != 0) /* Not at end of file. Back up a record. */ /* SetFilePoiner is more convenient here than SetFilePointerEx since the move is a short shift from the current position */ SetFilePointer (hJobData, -(LONG)SJM_JOB, NULL, FILE_CURRENT); /* Enter the new Job record. */ jobRecord.ProcessId = pProcessInfo->dwProcessId; _tcsnccpy_s (jobRecord.CommandLine, sizeof(jobRecord.CommandLine), Command, MAX_PATH); WriteFile (hJobData, &jobRecord, SJM_JOB, &nXfer, NULL); } __finally { /* Release the lock on the file. */ UnlockFileEx (hJobData, 0, fileSizePlus.LowPart, fileSizePlus.HighPart, ®ionStart); CloseHandle (hJobData); } return jobNumber + 1; }
///<summary>Checks whether the given file is a valid image file.</summary> ///<param name="szFile">The path to the file to check.</param> ///<returns>Whether the file is valid.</summary> BOOL IsValidImageFile(LPTSTR szFile) { TCHAR szFileExt[8] = { 0 }; // The file extension of the actual file DWORD dwExtSize; // Size of the file extension TCHAR szFilterExt[8] = { 0 }; // The current filter extension being compared BOOL bIsValidExt = FALSE; TCHAR* curChar; TCHAR period = TEXT('.'); TCHAR* lastPeriod = NULL; for (curChar = szFile; *curChar != 0; curChar++) { if (*curChar == period) lastPeriod = curChar; } // No file extension? Definitely not valid then if (lastPeriod == NULL) return FALSE; // Extension size of 0 or greater than 7? Never heard of that format... dwExtSize = (DWORD)(curChar - lastPeriod - 1); if (!dwExtSize || dwExtSize > 7) { return FALSE; } // Save the extension and convert it to uppercase for comparison with our filter _tcsnccpy_s(szFileExt, lastPeriod + 1, dwExtSize + 1); // + 1 will copy the null terminator too for (curChar = szFileExt; *curChar != 0; curChar++) { *curChar = _totupper(*curChar); } // Yep, I'm re-using variables // Skip the description part of our filter to get to the actual extensions for (curChar = szFilter; *curChar != 0; curChar++); curChar += 3; // Skip to first character of the first extension lastPeriod = curChar - 1; // Compare each valid file extension against the one for our image for (; *curChar != 0; curChar++) { if (*curChar == TEXT(';')) { dwExtSize = (DWORD)(curChar - lastPeriod - 1); _tcsnccpy_s(szFilterExt, lastPeriod + 1, dwExtSize); szFilterExt[dwExtSize + 1] = 0; if (_tccmp(szFileExt, szFilterExt) == 0) { bIsValidExt = TRUE; break; } curChar += 3; // Skip the "*." after the semicolon in the list lastPeriod = curChar - 1; } } // Final comparison if there's no trailing semicolon if (*(curChar - 1) != TEXT(';') && !bIsValidExt) { dwExtSize = (DWORD)(curChar - lastPeriod - 1); _tcsnccpy_s(szFilterExt, lastPeriod + 1, dwExtSize); szFilterExt[dwExtSize + 1] = 0; if (_tccmp(szFileExt, szFilterExt) == 0) { bIsValidExt = TRUE; } } if (!bIsValidExt) return FALSE; // Finally, check if the file actually exists DWORD dwAttrib = GetFileAttributes(szFile); return dwAttrib != INVALID_FILE_ATTRIBUTES; }