You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
328 lines
9.7 KiB
328 lines
9.7 KiB
#ifndef CREATETEMPFILE_H
|
|
#define CREATETEMPFILE_H
|
|
|
|
|
|
#include <aclapi.h>
|
|
#include <shlwapi.h>
|
|
#include <shlobj.h>
|
|
|
|
|
|
/*
|
|
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
|