- /* Set the reparse data on the open file using the
- * FSCTL_SET_REPARSE_POINT ioctl.
- *
- * There are contradictions in Microsoft's documentation for this:
- *
- * "If hDevice was opened without specifying FILE_FLAG_OVERLAPPED,
- * lpOverlapped is ignored."
- *
- * --- So setting lpOverlapped to NULL is okay since it's ignored.
- *
- * "If lpOverlapped is NULL, lpBytesReturned cannot be NULL. Even when an
- * operation returns no output data and lpOutBuffer is NULL,
- * DeviceIoControl makes use of lpBytesReturned. After such an
- * operation, the value of lpBytesReturned is meaningless."
- *
- * --- So lpOverlapped not really ignored, as it affects another
- * parameter. This is the actual behavior: lpBytesReturned must be
- * specified, even though lpBytesReturned is documented as:
- *
- * "Not used with this operation; set to NULL."
- */
- if (!DeviceIoControl(h, FSCTL_SET_REPARSE_POINT, rpbuf,
- rpbuflen,
- NULL, 0,
- &bytesReturned /* lpBytesReturned */,
- NULL /* lpOverlapped */))
- {
- DWORD err = GetLastError();
- if (err == ERROR_ACCESS_DENIED || err == ERROR_PRIVILEGE_NOT_HELD)
- {
- args->num_soft_links_failed++;
- if (args->num_soft_links_failed <= MAX_CREATE_SOFT_LINK_WARNINGS) {
- WARNING("Can't set reparse data on \"%ls\": Access denied!\n"
- " You may be trying to extract a symbolic "
- "link without the\n"
- " SeCreateSymbolicLink privilege, which by "
- "default non-Administrator\n"
- " accounts do not have.", path);
- }
- if (args->num_hard_links_failed == MAX_CREATE_HARD_LINK_WARNINGS) {
- WARNING("Suppressing further warnings regarding failure to extract\n"
- " reparse points due to insufficient privileges...");
- }
- } else {
- ERROR("Failed to set reparse data on \"%ls\"", path);
- win32_error(err);
- if (inode->i_reparse_tag == WIM_IO_REPARSE_TAG_SYMLINK ||
- inode->i_reparse_tag == WIM_IO_REPARSE_TAG_MOUNT_POINT)
- return WIMLIB_ERR_LINK;
- else
- return WIMLIB_ERR_WRITE;
- }
- }