#ifndef CREATETEMPFILE_H #define CREATETEMPFILE_H #include #include #include /* Routine Name: CreateTempFile Routine Description: Creates a temporary file only the caller can access. Arguments: pszTempFileName [in/out] Pointer to a null terminated string that is the full path to the temp file or receives the full path to the temp file if bCreateName is TRUE. You should set the size of this buffer to MAX_PATH to ensure that it is large enough to hold the returned string. pszExtension [in] Pointer to a null terminated string that specifies the extension of the file name to be created.If pszExtension is NULL, the default extension is tmp. bCreateName [in] Species whether pszTempFileName should receive a temp file name generated by the function. if bCreateName is TRUE, a temp file in user's temp directory is created and full path to the file is returned to the caller in pszTempFileName. dwFlags [in] Specifies the file attributes and flags for the file. Return Values: If the function succeeds, the return value is a handle to the temp file. if the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information call GetLastError() Author: gokmenh, March, 2002 */ inline HANDLE _CreateTempFile ( LPTSTR pszTempFileName, LPTSTR pszExtension = NULL, BOOL bCreateName = TRUE, DWORD dwFlags = 0 ) { TCHAR szTempPath[MAX_PATH]; TCHAR szTempFile[MAX_PATH]; DWORD dwRC = ERROR_SUCCESS; DWORD dwLength; TOKEN_USER * pTokenUser = NULL; EXPLICIT_ACCESS ea[1]; PACL pACL = NULL; PSECURITY_DESCRIPTOR pSD = NULL; SECURITY_ATTRIBUTES sa; HANDLE hFile = INVALID_HANDLE_VALUE; HANDLE hToken = NULL; BOOL bCreateDir = FALSE; szTempPath[0] = NULL; szTempFile[0] = NULL; ZeroMemory( ea, sizeof(ea) ); if (NULL == pszTempFileName) { SetLastError(ERROR_INVALID_PARAMETER); return INVALID_HANDLE_VALUE; } // If the caller does not specify the file name we // need to come up with our own. if (TRUE == bCreateName) { if (0 == GetTempPath(sizeof(szTempPath)/sizeof(TCHAR), szTempPath)) { dwRC = GetLastError(); } if (ERROR_SUCCESS == dwRC) { if (0 == GetTempFileName(szTempPath, _T("tmp"), 0, szTempFile)) { dwRC = GetLastError(); } else { if (NULL != pszExtension) { // We will change the extension, get rid of the file with the old extension if (FALSE == DeleteFile(szTempFile)) { dwRC = GetLastError(); } if (ERROR_SUCCESS == dwRC) { if (FALSE == PathRenameExtension(szTempFile, pszExtension)) { dwRC = ERROR_INVALID_DATA; } } } } } } else { szTempPath[MAX_PATH - 1] = NULL; _tcsncpy(szTempFile, pszTempFileName, MAX_PATH); _tcsncpy(szTempPath, pszTempFileName, MAX_PATH); if (NULL != szTempPath[MAX_PATH - 1]) { dwRC = ERROR_INVALID_PARAMETER; } } if (ERROR_SUCCESS == dwRC) { // We will first try to get to the impersonation token for the thread if (0 == OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken)) { dwRC = GetLastError(); if (ERROR_NO_TOKEN == dwRC) { // It seems that the thread is not doing impersonation. We will stick to the // process token if (0 == OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { dwRC = GetLastError(); } else { dwRC = ERROR_SUCCESS; } } } } if (ERROR_SUCCESS == dwRC) { // First try to obtain how much space we need if (0 == GetTokenInformation(hToken, TokenUser, NULL, 0, &dwLength)) { dwRC = GetLastError(); if (ERROR_INSUFFICIENT_BUFFER == dwRC) { // Allocate the required memory and retry. dwRC = ERROR_SUCCESS; pTokenUser = (TOKEN_USER *) new BYTE[dwLength]; if (NULL == pTokenUser) { dwRC = ERROR_NOT_ENOUGH_MEMORY; } else if (0 == GetTokenInformation(hToken, TokenUser, pTokenUser, dwLength, &dwLength)) { dwRC = GetLastError(); } } } else { // GetTokenInformation works with a NULL pointer? dwRC = ERROR_INVALID_DATA; } } if (ERROR_SUCCESS == dwRC) { // We now have the token info for the current user which contains the sid for the user. // We will try to create a security descriptor which allows only the user to access the file. ea[0].grfAccessPermissions = GENERIC_ALL; ea[0].grfAccessMode = SET_ACCESS; ea[0].grfInheritance = NO_INHERITANCE; ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[0].Trustee.TrusteeType = TRUSTEE_IS_GROUP; ea[0].Trustee.ptstrName = (LPTSTR) pTokenUser->User.Sid; dwRC = SetEntriesInAcl(1, ea, NULL, &pACL); } if (ERROR_SUCCESS == dwRC) { pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); if (NULL == pSD) { dwRC = ERROR_NOT_ENOUGH_MEMORY; } } if (ERROR_SUCCESS == dwRC) { if ( 0 == InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { dwRC = GetLastError(); } } if (ERROR_SUCCESS == dwRC) { if (0 == SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE)) { dwRC = GetLastError(); } } if (ERROR_SUCCESS == dwRC) { sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = FALSE; sa.lpSecurityDescriptor = pSD; if (FALSE == bCreateName) { if (FALSE == PathRemoveFileSpec(szTempPath)) { dwRC = ERROR_INVALID_PARAMETER; } else { // We do not want to create root dirs if (FALSE == PathIsRoot(szTempPath)) { dwRC = SHCreateDirectoryEx(NULL, szTempPath, &sa); if ((ERROR_FILE_EXISTS == dwRC) || (ERROR_ALREADY_EXISTS == dwRC)) { dwRC = ERROR_SUCCESS; } } } } } if (ERROR_SUCCESS == dwRC) { hFile = CreateFile ( szTempFile, GENERIC_ALL, FILE_SHARE_READ, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | dwFlags, NULL ); dwRC = GetLastError(); if (INVALID_HANDLE_VALUE != hFile) { if (ERROR_ALREADY_EXISTS == dwRC) { // If the file already exists, we will still have a handle to the file but // CreateFile does not change the security descriptor for the file so we need // to make sure that we ACL the file properly. dwRC = SetNamedSecurityInfo ( (LPTSTR) szTempFile, // File name SE_FILE_OBJECT, // This is a file DACL_SECURITY_INFORMATION | // We will pass in an ACL PROTECTED_DACL_SECURITY_INFORMATION, // File will not inherit anything from the parent NULL, // Owner sid NULL, // Group sid pACL, // ACL NULL // SACL ); } } } if (NULL != pSD) { LocalFree(pSD); } if (NULL != pACL) { LocalFree(pACL); } if (NULL != pTokenUser) { delete [] (LPBYTE) pTokenUser; } if (NULL != hToken) { CloseHandle(hToken); } if (ERROR_SUCCESS == dwRC) { _tcsncpy(pszTempFileName, szTempFile, MAX_PATH); return hFile; } else { if (INVALID_HANDLE_VALUE != hFile) { CloseHandle(hFile); } SetLastError(dwRC); return INVALID_HANDLE_VALUE; } } #endif