//go:build windows

package yu_sys

import (
	_ "unsafe"
)

//go:cgo_import_dynamic LoadLibraryW LoadLibraryW "kernel32.dll"
//go:linkname LoadLibraryW LoadLibraryW
var LoadLibraryW Address

//go:cgo_import_dynamic MultiByteToWideChar MultiByteToWideChar "kernel32.dll"
//go:linkname MultiByteToWideChar MultiByteToWideChar
var MultiByteToWideChar Address

//go:cgo_import_dynamic WideCharToMultiByte WideCharToMultiByte "kernel32.dll"
//go:linkname WideCharToMultiByte WideCharToMultiByte
var WideCharToMultiByte Address

//go:cgo_import_dynamic GetProcAddress GetProcAddress "kernel32.dll"
//go:linkname GetProcAddress GetProcAddress
var GetProcAddress Address

//go:cgo_import_dynamic GlobalAlloc GlobalAlloc "kernel32.dll"
//go:linkname GlobalAlloc GlobalAlloc
var GlobalAlloc Address

//go:cgo_import_dynamic GlobalFree GlobalFree "kernel32.dll"
//go:linkname GlobalFree GlobalFree
var GlobalFree Address

//go:cgo_import_dynamic GlobalLock GlobalLock "kernel32.dll"
//go:linkname GlobalLock GlobalLock
var GlobalLock Address

//go:cgo_import_dynamic GlobalSize GlobalSize "kernel32.dll"
//go:linkname GlobalSize GlobalSize
var GlobalSize Address

//go:cgo_import_dynamic GlobalUnlock GlobalUnlock "kernel32.dll"
//go:linkname GlobalUnlock GlobalUnlock
var GlobalUnlock Address

const (
	// GHND 组合了 GMEM_MOVEABLE 和 GMEM_ZEROINIT
	GHND = 0x0042
	// GMEM_FIXED 分配固定内存。返回值是一个指针。
	GMEM_FIXED = 0x0000
	// GMEM_MOVEABLE 分配可移动的内存。内存块在物理内存中从不移动，但它们可以在默认堆中移动。
	// 返回值是内存对象的句柄。要将句柄转换为指针，使用 GlobalLock 函数。
	// 该值不能与 GMEM_FIXED 组合。
	GMEM_MOVEABLE = 0x0002
	// GMEM_ZEROINIT 将内存内容初始化为零。
	GMEM_ZEROINIT = 0x0040
	// GPTR 组合了 GMEM_FIXED 和 GMEM_ZEROINIT
	GPTR = 0x0040
)

//go:cgo_import_dynamic GetFileAttributesW GetFileAttributesW "kernel32.dll"
//go:linkname GetFileAttributesW GetFileAttributesW
var GetFileAttributesW Address

//go:cgo_import_dynamic CreateFileW CreateFileW "kernel32.dll"
//go:linkname CreateFileW CreateFileW
var CreateFileW Address

//go:cgo_import_dynamic CloseHandle CloseHandle "kernel32.dll"
//go:linkname CloseHandle CloseHandle
var CloseHandle Address

//go:cgo_import_dynamic GetFileSizeEx GetFileSizeEx "kernel32.dll"
//go:linkname GetFileSizeEx GetFileSizeEx
var GetFileSizeEx Address

//go:cgo_import_dynamic ReadFile ReadFile "kernel32.dll"
//go:linkname ReadFile ReadFile
var ReadFile Address

//go:cgo_import_dynamic WriteFile WriteFile "kernel32.dll"
//go:linkname WriteFile WriteFile
var WriteFile Address

//go:cgo_import_dynamic SetFilePointerEx SetFilePointerEx "kernel32.dll"
//go:linkname SetFilePointerEx SetFilePointerEx
var SetFilePointerEx Address

//go:cgo_import_dynamic SetEndOfFile SetEndOfFile "kernel32.dll"
//go:linkname SetEndOfFile SetEndOfFile
var SetEndOfFile Address

//go:cgo_import_dynamic FindFirstFileW FindFirstFileW "kernel32.dll"
//go:linkname FindFirstFileW FindFirstFileW
var FindFirstFileW Address

//go:cgo_import_dynamic FindNextFileW FindNextFileW "kernel32.dll"
//go:linkname FindNextFileW FindNextFileW
var FindNextFileW Address

//go:cgo_import_dynamic FindClose FindClose "kernel32.dll"
//go:linkname FindClose FindClose
var FindClose Address

const (
	// 摘自：https://learn.microsoft.com/zh-cn/windows/win32/fileio/file-attribute-constants

	FILE_ATTRIBUTE_READONLY              = 1       // (0x00000001) 只读文件。 应用程序可以读取文件，但不能写入或删除该文件。 在目录上不遵循此属性。 有关详细信息，请参阅 无法在 Windows Server 2003、Windows XP、Windows Vista 或 Windows 7 中查看或更改文件夹的只读或系统属性。
	FILE_ATTRIBUTE_HIDDEN                = 2       // (0x00000002) 文件或目录处于隐藏状态。 它不包括在普通目录列表中。
	FILE_ATTRIBUTE_SYSTEM                = 4       // (0x00000004) 操作系统使用其中的一部分或独占使用的文件或目录。
	FILE_ATTRIBUTE_DIRECTORY             = 16      // (0x00000010) 标识目录的句柄。
	FILE_ATTRIBUTE_ARCHIVE               = 32      // (0x00000020) 作为存档文件或目录的文件或目录。 应用程序通常使用此属性来标记要备份或删除的文件。
	FILE_ATTRIBUTE_DEVICE                = 64      // (0x00000040) 此值保留供系统使用。
	FILE_ATTRIBUTE_NORMAL                = 128     // (0x00000080) 未设置其他属性的文件。 此属性仅在单独使用时才有效。
	FILE_ATTRIBUTE_TEMPORARY             = 256     // (0x00000100) 用于临时存储的文件。 如果有足够的缓存内存可用，文件系统会避免将数据写回到大容量存储，因为通常情况下，应用程序在句柄关闭后会删除临时文件。 在这种情况下，系统可以完全避免写入数据。 否则，在句柄关闭后写入数据。
	FILE_ATTRIBUTE_SPARSE_FILE           = 512     // (0x00000200) 是稀疏文件的文件。
	FILE_ATTRIBUTE_REPARSE_POINT         = 1024    // (0x00000400) 具有关联的重新分析点的文件或目录，或作为符号链接的文件。
	FILE_ATTRIBUTE_COMPRESSED            = 2048    // (0x00000800) 压缩的文件或目录。 对于文件，将压缩该文件中的所有数据。 对于目录，压缩是新建文件和子目录的默认设置。
	FILE_ATTRIBUTE_OFFLINE               = 4096    // (0x00001000) 文件的数据不会立即可用。 此属性指示文件数据以物理方式移动到脱机存储。 此属性由远程存储（分层存储管理软件）使用。 应用程序不应随意更改此属性。
	FILE_ATTRIBUTE_NOT_CONTENT_INDEXED   = 8192    // (0x00002000) 内容索引服务不会为文件或目录编制索引。
	FILE_ATTRIBUTE_ENCRYPTED             = 16384   // (0x00004000) 加密的文件或目录。 对于文件，文件中的所有数据流都已加密。 对于目录，加密是新创建的文件和子目录的默认加密。
	FILE_ATTRIBUTE_INTEGRITY_STREAM      = 32768   // (0x00008000) 目录或用户数据流配置了完整性 (仅在 ReFS 卷) 上受支持。 它不包括在普通目录列表中。 如果文件已重命名，完整性设置将一直保留。 如果复制了某个文件，则如果源文件或目标目录设置了完整性，则目标文件将具有完整性设置。Windows Server 2008 R2、Windows 7、Windows Server 2008、Windows Vista、Windows Server 2003 和 Windows XP：在Windows Server 2012之前，不支持此标志。
	FILE_ATTRIBUTE_VIRTUAL               = 65536   // (0x00010000) 此值保留供系统使用。
	FILE_ATTRIBUTE_NO_SCRUB_DATA         = 131072  // (0x00020000) 后台数据完整性扫描程序不读取的用户数据流 (AKA 清理器) 。 在目录上设置时，它仅提供继承。 此标志仅在 存储空间 和 ReFS 卷上受支持。 它不包括在普通目录列表中。Windows Server 2008 R2、Windows 7、Windows Server 2008、Windows Vista、Windows Server 2003 和 Windows XP：在Windows 8和Windows Server 2012之前，不支持此标志。
	FILE_ATTRIBUTE_EA                    = 262144  // (0x00040000) 具有扩展属性的文件或目录。重要： 此常量仅供内部使用。
	FILE_ATTRIBUTE_PINNED                = 524288  // (0x00080000) 此属性指示用户意图，即即使未主动访问文件或目录，也应在本地保持完全存在。 此属性用于分层存储管理软件。
	FILE_ATTRIBUTE_UNPINNED              = 1048576 // (0x00100000) 此属性指示，除非主动访问文件或目录，否则不应在本地完全存在。 此属性用于分层存储管理软件。
	FILE_ATTRIBUTE_RECALL_ON_OPEN        = 262144  // (0x00040000) 此属性仅出现在目录枚举类 (FILE_DIRECTORY_INFORMATION、FILE_BOTH_DIR_INFORMATION等) 中。 设置此属性时，这意味着文件或目录在本地系统上没有物理表示形式;项是虚拟的。 打开该项目的成本将比平常要高，例如，它会导致至少从远程存储中提取其中一部分。
	FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS = 4194304 // (0x00400000) 如果设置了此属性，则意味着文件或目录在本地未完全存在。 对于表示并非所有数据都位于本地存储 (的文件，例如，它可能稀疏，某些数据仍位于远程存储) 中。 对于目录，这意味着某些目录内容正在从另一个位置虚拟化。 读取文件/枚举目录的成本将比平常要高，例如，这会导致至少从远程存储中提取一些文件/目录内容。 只有内核模式调用方可以设置此位。文件系统微型筛选器低于 180000 – 189999高度范围 (FSFilter HSM 加载顺序组) 不得对设置了此属性的文件发出目标缓存读取或写入。 这可能会导致缓存污染和潜在的文件损坏。 有关详细信息，请参阅 处理占位符。
)

const (
	// 摘自：https://learn.microsoft.com/zh-cn/windows/win32/secauthz/generic-access-rights

	GENERIC_ALL             = 0x10000000 // 所有可能的访问权限
	GENERIC_EXECUTE         = 0x20000000 // 执行访问权限
	GENERIC_WRITE           = 0x40000000 // 写入权限
	GENERIC_READ    uintptr = 0x80000000 // 读取权限
)

const (
	// 摘自：https://learn.microsoft.com/zh-cn/windows/win32/fileio/file-access-rights-constants

	FILE_APPEND_DATA = 0x00000004 // 对于文件对象，是将数据追加到文件的权限。 (对于本地文件，如果未指定此标志，写入操作将不会覆盖现有数据 FILE_WRITE_DATA。) 对于目录对象，创建子目录 (的权限 FILE_ADD_SUBDIRECTORY) 。
)

const (
	// 摘自：https://learn.microsoft.com/zh-cn/windows/win32/api/fileapi/nf-fileapi-createfilew

	FILE_SHARE_NO     = 0x00000000 // 如果文件或设备请求删除、读取或写入访问权限，则阻止后续打开操作。
	FILE_SHARE_DELETE = 0x00000004 // 启用文件或设备上的后续打开操作以请求删除访问权限。否则，如果进程请求删除访问权限，则任何进程都无法打开该文件或设备。如果未指定此标志，但已打开文件或设备进行删除访问，则函数将失败。注意 删除访问权限允许删除和重命名操作。
	FILE_SHARE_READ   = 0x00000001 // 启用文件或设备上的后续打开操作以请求读取访问权限。否则，如果进程请求读取访问权限，则任何进程都无法打开该文件或设备。如果未指定此标志，但已打开文件或设备进行读取访问，则函数将失败。
	FILE_SHARE_WRITE  = 0x00000002 // 启用文件或设备上的后续打开操作以请求写入访问权限。否则，如果进程请求写入访问权限，则任何进程都无法打开该文件或设备。如果未指定此标志，但已打开文件或设备进行写入访问，或者具有具有写入访问权限的文件映射，则函数将失败。
)

const (
	// 摘自：https://learn.microsoft.com/zh-cn/windows/win32/api/fileapi/nf-fileapi-createfilew

	CREATE_NEW        = 1 // 仅当文件尚不存在时才创建一个新文件。如果指定的文件存在，则函数将失败，最后一个错误代码设置为 ERROR_FILE_EXISTS (80) 。如果指定的文件不存在，并且是可写位置的有效路径，则会创建一个新文件。
	CREATE_ALWAYS     = 2 // 始终创建新文件。如果指定的文件存在且可写，则函数将覆盖文件，函数成功，最后错误代码设置为 ERROR_ALREADY_EXISTS (183) 。如果指定的文件不存在并且是有效路径，则创建新文件，函数成功，最后错误代码设置为零。有关详细信息，请参阅本主题的“备注”部分。
	OPEN_EXISTING     = 3 // 仅当文件或设备存在时才打开它。如果指定的文件或设备不存在，则 函数将失败，最后一个错误代码设置为 ERROR_FILE_NOT_FOUND (2) 。有关设备的详细信息，请参阅备注部分。
	OPEN_ALWAYS       = 4 // 始终打开文件。如果指定的文件存在，则函数成功，最后错误代码设置为 ERROR_ALREADY_EXISTS (183) 。如果指定的文件不存在，并且是可写位置的有效路径，则函数将创建一个文件，并将最后一个错误代码设置为零。
	TRUNCATE_EXISTING = 5 // 打开一个文件并截断它，使其大小为零字节（仅当它存在时）。如果指定的文件不存在，则函数将失败，最后一个错误代码设置为 ERROR_FILE_NOT_FOUND (2) 。调用进程必须打开文件，并将 GENERIC_WRITE 位设置为 dwDesiredAccess 参数的一部分。
)

const (
	// 摘自：https://learn.microsoft.com/zh-cn/windows/win32/api/fileapi/nf-fileapi-createfilew

	FILE_FLAG_OPEN_NO_RECALL             = 0x00100000 // 文件数据已请求，但应继续位于远程存储中。 不应将其传输回本地存储。 此标志供远程存储系统使用。
	FILE_FLAG_OPEN_REPARSE_POINT         = 0x00200000 // 不会进行正常的 重分析点 处理; CreateFile 将尝试打开重新分析点。 打开文件时，无论控制重分析点的筛选器是否正常运行，都返回文件句柄。此标志不能与 CREATE_ALWAYS 标志一起使用。如果文件不是重分析点，则忽略此标志。有关详细信息，请参见“备注”部分。
	FILE_FLAG_SESSION_AWARE              = 0x00800000 // 正在使用会话感知打开文件或设备。 如果未指定此标志，则会话 0 中运行的进程无法打开每个会话设备 (，例如使用 RemoteFX USB 重定向) 的设备。 此标志对不在会话 0 中的调用方不起作用。 此标志仅在 Windows 的服务器版本上受支持。Windows Server 2008 R2 和 Windows Server 2008： 在Windows Server 2012之前，不支持此标志。
	FILE_FLAG_POSIX_SEMANTICS            = 0x01000000 // 将根据 POSIX 规则进行访问。 这包括允许多个具有名称的文件（仅在大小写上不同）用于支持该命名的文件系统。 使用此选项时请小心，因为为 MS-DOS 或 16 位 Windows 编写的应用程序可能无法访问使用此标志创建的文件。
	FILE_FLAG_BACKUP_SEMANTICS           = 0x02000000 // 正在为备份或还原操作打开或创建文件。 当进程具有 SE_BACKUP_NAME 和 SE_RESTORE_NAME 权限时，系统将确保调用进程替代文件安全检查。 有关详细信息，请参阅 更改令牌中的特权。必须设置此标志才能获取目录的句柄。 目录句柄可以传递给某些函数，而不是文件句柄。 有关详细信息，请参见“备注”部分。
	FILE_FLAG_DELETE_ON_CLOSE            = 0x04000000 // 文件在其所有句柄都关闭后立即被删除，其中包括指定的句柄和任何其他打开或重复的句柄。如果存在文件的现有打开句柄，则调用会失败，除非它们都以 FILE_SHARE_DELETE 共享模式打开。针对文件的后续打开请求将失败，除非指定 FILE_SHARE_DELETE 共享模式。
	FILE_FLAG_SEQUENTIAL_SCAN            = 0x08000000 // 访问旨在从头到尾按顺序进行。 系统可将此选项用作优化文件缓存的提示。如果读取隐藏 (即将使用反向扫描) ，则不应使用此标志。如果文件系统不支持缓存的 I/O 和 FILE_FLAG_NO_BUFFERING 则此标志不起作用。有关详细信息，请参阅本主题的 缓存行为 部分。
	FILE_FLAG_RANDOM_ACCESS              = 0x10000000 // 访问应是随机的。 系统可将此选项用作优化文件缓存的提示。如果文件系统不支持缓存的 I/O 且 FILE_FLAG_NO_BUFFERING 则此标志无效。有关详细信息，请参阅本主题的 缓存行为 部分。
	FILE_FLAG_NO_BUFFERING               = 0x20000000 // 正在打开文件或设备，没有系统缓存用于数据读取和写入。 此标志不会影响硬盘缓存或内存映射文件。使用 FILE_FLAG_NO_BUFFERING 标志成功处理使用 CreateFile 打开的文件有严格的要求，有关详细信息，请参阅文件缓冲。
	FILE_FLAG_OVERLAPPED                 = 0x40000000 // 正在为异步 I/O 打开或创建文件或设备。在此句柄上完成后续 I/O 操作时， OVERLAPPED 结构中指定的事件将设置为信号状态。如果指定了此标志，则文件可用于同时读取和写入操作。如果未指定此标志，则 I/O 操作将序列化，即使对读取和写入函数的调用指定 了 OVERLAPPED 结构也是如此。有关使用此标志创建的文件句柄时的注意事项的信息，请参阅本主题的 同步和异步 I/O 句柄 部分。
	FILE_FLAG_WRITE_THROUGH      uintptr = 0x80000000 // 写入操作不会经过任何中间缓存，它们将直接转到磁盘。有关其他信息，请参阅本主题的 缓存行为 部分。
)

const (
	// 摘自：https://learn.microsoft.com/zh-cn/windows/win32/api/fileapi/nf-fileapi-setfilepointerex

	FILE_BEGIN   = 0 // 起始点为零或文件的开头。 如果指定了此标志，则 liDistanceToMove 参数将解释为无符号值。
	FILE_CURRENT = 1 // 起点是文件指针的当前值。
	FILE_END     = 2 // 起点是当前文件结束位置。
)

type FindData struct {
	FileAttributes    uint32
	CreationTime      Filetime
	LastAccessTime    Filetime
	LastWriteTime     Filetime
	FileSizeHigh      uint32
	FileSizeLow       uint32
	Reserved0         uint32
	Reserved1         uint32
	FileName          [520]byte // 256*2 + 8
	AlternateFileName [30]byte  // 14*2 + 2
}

type Filetime struct {
	LowDateTime  uint32
	HighDateTime uint32
}
