📄 create.c
字号:
NULL,
NULL);
if (lpSecurityAttributes)
{
if(lpSecurityAttributes->bInheritHandle)
ObjectAttributes.Attributes |= OBJ_INHERIT;
ObjectAttributes.SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
}
if(!(dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS))
ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
/* perform the call */
Status = NtCreateFile (&FileHandle,
dwDesiredAccess,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FileAttributes,
dwShareMode,
dwCreationDisposition,
Flags,
EaBuffer,
EaLength);
RtlFreeHeap(RtlGetProcessHeap(),
0,
NtPathU.Buffer);
/* free the extended attributes buffer if allocated */
if (EaBuffer != NULL)
{
RtlFreeHeap(RtlGetProcessHeap(),
0,
EaBuffer);
}
/* error */
if (!NT_SUCCESS(Status))
{
/* In the case file creation was rejected due to CREATE_NEW flag
* was specified and file with that name already exists, correct
* last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS.
* Note: RtlNtStatusToDosError is not the subject to blame here.
*/
if (Status == STATUS_OBJECT_NAME_COLLISION &&
dwCreationDisposition == FILE_CREATE)
{
SetLastError( ERROR_FILE_EXISTS );
}
else
{
SetLastErrorByStatus (Status);
}
return INVALID_HANDLE_VALUE;
}
/*
create with OPEN_ALWAYS (FILE_OPEN_IF) returns info = FILE_OPENED or FILE_CREATED
create with CREATE_ALWAYS (FILE_OVERWRITE_IF) returns info = FILE_OVERWRITTEN or FILE_CREATED
*/
if (dwCreationDisposition == FILE_OPEN_IF)
{
SetLastError(IoStatusBlock.Information == FILE_OPENED ? ERROR_ALREADY_EXISTS : 0);
}
else if (dwCreationDisposition == FILE_OVERWRITE_IF)
{
SetLastError(IoStatusBlock.Information == FILE_OVERWRITTEN ? ERROR_ALREADY_EXISTS : 0);
}
return FileHandle;
}
/*
* @implemented
*/
BOOLEAN
STDCALL
CreateSymbolicLinkW(IN LPCWSTR lpSymlinkFileName,
IN LPCWSTR lpTargetFileName,
IN DWORD dwFlags)
{
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE hSymlink = NULL;
UNICODE_STRING SymlinkFileName = { 0, 0, NULL };
UNICODE_STRING TargetFileName = { 0, 0, NULL };
BOOLEAN bAllocatedTarget = FALSE, bRelativePath = FALSE;
LPWSTR lpTargetFullFileName = NULL;
SIZE_T cbPrintName;
SIZE_T cbReparseData;
PREPARSE_DATA_BUFFER pReparseData = NULL;
PBYTE pBufTail;
NTSTATUS Status;
ULONG dwCreateOptions;
DWORD dwErr;
if(!lpSymlinkFileName || !lpTargetFileName || (dwFlags | SYMBOLIC_LINK_FLAG_DIRECTORY) != SYMBOLIC_LINK_FLAG_DIRECTORY)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if(dwFlags & SYMBOLIC_LINK_FLAG_DIRECTORY)
dwCreateOptions = FILE_DIRECTORY_FILE;
else
dwCreateOptions = FILE_NON_DIRECTORY_FILE;
switch(RtlDetermineDosPathNameType_U(lpTargetFileName))
{
case RtlPathTypeUnknown:
case RtlPathTypeRooted:
case RtlPathTypeRelative:
bRelativePath = TRUE;
RtlInitUnicodeString(&TargetFileName, lpTargetFileName);
break;
case RtlPathTypeDriveRelative:
{
LPWSTR FilePart;
SIZE_T cchTargetFullFileName;
cchTargetFullFileName = GetFullPathNameW(lpTargetFileName, 0, NULL, &FilePart);
if(cchTargetFullFileName == 0)
{
dwErr = GetLastError();
goto Cleanup;
}
lpTargetFullFileName = RtlAllocateHeap(RtlGetProcessHeap(), 0, cchTargetFullFileName * sizeof(WCHAR));
if(lpTargetFullFileName == NULL)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
if(GetFullPathNameW(lpTargetFileName, cchTargetFullFileName, lpTargetFullFileName, &FilePart) == 0)
{
dwErr = GetLastError();
goto Cleanup;
}
}
lpTargetFileName = lpTargetFullFileName;
// fallthrough
case RtlPathTypeUncAbsolute:
case RtlPathTypeDriveAbsolute:
case RtlPathTypeLocalDevice:
case RtlPathTypeRootLocalDevice:
default:
if(!RtlDosPathNameToNtPathName_U(lpTargetFileName, &TargetFileName, NULL, NULL))
{
bAllocatedTarget = TRUE;
dwErr = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
}
cbPrintName = wcslen(lpTargetFileName) * sizeof(WCHAR);
cbReparseData = FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + TargetFileName.Length + cbPrintName;
pReparseData = RtlAllocateHeap(RtlGetProcessHeap(), 0, cbReparseData);
if(pReparseData == NULL)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
pBufTail = (PBYTE)(pReparseData->SymbolicLinkReparseBuffer.PathBuffer);
pReparseData->ReparseTag = (ULONG)IO_REPARSE_TAG_SYMLINK;
pReparseData->ReparseDataLength = (USHORT)cbReparseData - REPARSE_DATA_BUFFER_HEADER_SIZE;
pReparseData->Reserved = 0;
pReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
pReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength = TargetFileName.Length;
pBufTail += pReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset;
RtlCopyMemory(pBufTail, TargetFileName.Buffer, TargetFileName.Length);
pReparseData->SymbolicLinkReparseBuffer.PrintNameOffset = pReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
pReparseData->SymbolicLinkReparseBuffer.PrintNameLength = (USHORT)cbPrintName;
pBufTail += pReparseData->SymbolicLinkReparseBuffer.PrintNameOffset;
RtlCopyMemory(pBufTail, lpTargetFileName, cbPrintName);
pReparseData->SymbolicLinkReparseBuffer.Flags = 0;
if(bRelativePath)
pReparseData->SymbolicLinkReparseBuffer.Flags |= 1; // TODO! give this lone flag a name
if(!RtlDosPathNameToNtPathName_U(lpSymlinkFileName, &SymlinkFileName, NULL, NULL))
{
dwErr = ERROR_PATH_NOT_FOUND;
goto Cleanup;
}
InitializeObjectAttributes(&ObjectAttributes, &SymlinkFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = NtCreateFile
(
&hSymlink,
FILE_WRITE_ATTRIBUTES | DELETE | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_CREATE,
FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT | dwCreateOptions,
NULL,
0
);
if(!NT_SUCCESS(Status))
{
dwErr = RtlNtStatusToDosError(Status);
goto Cleanup;
}
Status = NtFsControlFile
(
hSymlink,
NULL,
NULL,
NULL,
&IoStatusBlock,
FSCTL_SET_REPARSE_POINT,
pReparseData,
cbReparseData,
NULL,
0
);
if(!NT_SUCCESS(Status))
{
FILE_DISPOSITION_INFORMATION DispInfo;
DispInfo.DeleteFile = TRUE;
NtSetInformationFile(hSymlink, &IoStatusBlock, &DispInfo, sizeof(DispInfo), FileDispositionInformation);
dwErr = RtlNtStatusToDosError(Status);
goto Cleanup;
}
dwErr = NO_ERROR;
Cleanup:
if(hSymlink)
NtClose(hSymlink);
RtlFreeUnicodeString(&SymlinkFileName);
if (bAllocatedTarget)
{
RtlFreeHeap(RtlGetProcessHeap(),
0,
TargetFileName.Buffer);
}
if(lpTargetFullFileName)
RtlFreeHeap(RtlGetProcessHeap(), 0, lpTargetFullFileName);
if(pReparseData)
RtlFreeHeap(RtlGetProcessHeap(), 0, pReparseData);
if(dwErr)
{
SetLastError(dwErr);
return FALSE;
}
return TRUE;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
CreateSymbolicLinkA(IN LPCSTR lpSymlinkFileName,
IN LPCSTR lpTargetFileName,
IN DWORD dwFlags)
{
PWCHAR SymlinkW, TargetW;
BOOLEAN Ret;
if(!lpSymlinkFileName || !lpTargetFileName)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (!(SymlinkW = FilenameA2W(lpSymlinkFileName, FALSE)))
return FALSE;
if (!(TargetW = FilenameA2W(lpTargetFileName, TRUE)))
return FALSE;
Ret = CreateSymbolicLinkW(SymlinkW,
TargetW,
dwFlags);
RtlFreeHeap(RtlGetProcessHeap(), 0, SymlinkW);
RtlFreeHeap(RtlGetProcessHeap(), 0, TargetW);
return Ret;
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -