在Windows API中只开放了两个允许区分大小写的API:
CreateFile,使用FILE_FLAG_POSIX_SEMANTICS开关;
FindFirstFileEx,使用FIND_FIRST_EX_CASE_SENSITIVE开关。
不过我们可以通过SetFileInformationByHandle来实现文件/文件夹的改名和删除。
此外,在Native API中InitializeObjectAttributes时不指定OBJ_CASE_INSENSITIVE开关,也可以实现区分大小写的功能。
所有的这些开关只有注册表键值obcaseinsensitive设为DWORD:0并且【重新启动】之后才有效。obcaseinsensitive的具体位置是HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\kernel。
这个键值只影响Windows API(kernel32.dll)和Native API(ntdll.dll)的行为,Windows Subsystem for Linux是通过未公开的内核调用来实现的,不受这个注册表键值影响。
// ConsoleApplication1.cpp: 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
int main()
{
HKEY hsubkey;
DWORD valtype, obcaseinsensitive, dwret;
LSTATUS lstatus;
ULONGLONG renbuf1[64], renbuf2[64];
FILE_RENAME_INFO *ren1, *ren2;
FILE_DISPOSITION_INFO del1, del2;
HANDLE hdir1, hdir2;
HANDLE hfind;
WIN32_FIND_DATA fd;
char ansipath[MAX_PATH];
// 检测系统是否打开了Win32的大小写敏感接口
hsubkey = NULL;
RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\kernel"), &hsubkey);
valtype = obcaseinsensitive = 0;
dwret = sizeof obcaseinsensitive;
lstatus = RegQueryValueEx(hsubkey, TEXT("obcaseinsensitive"), NULL, &valtype, (LPBYTE)&obcaseinsensitive, &dwret);
RegCloseKey(hsubkey);
if (lstatus != ERROR_SUCCESS || valtype != REG_DWORD || dwret != sizeof obcaseinsensitive ||
obcaseinsensitive != 0)
{
printf("HKEY_LOCAL_MACHINE\\CurrentControlSet\\Control\\Session Manager\\kernel\\obcaseinsensitive"
" must be set to REG_DWORD:0, and you must restart your computer before trying again.\n");
return 1;
}
// 创建两个文件夹
CreateDirectory(TEXT("G:\\CaseDir_1"), NULL);
CreateDirectory(TEXT("G:\\casedir_123"), NULL);
// 改成只有大小写不同的形式
// 第一个
hdir1 = CreateFile(TEXT("G:\\CaseDir_1"), GENERIC_READ | GENERIC_WRITE | DELETE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, NULL);
memset(renbuf1, 0, sizeof renbuf1);
ren1 = (FILE_RENAME_INFO*)renbuf1;
ren1->ReplaceIfExists = FALSE;
ren1->RootDirectory = NULL;
wcscpy(ren1->FileName, L"G:\\CaseDir");
ren1->FileNameLength = wcslen(ren1->FileName) * sizeof(wchar_t);
SetFileInformationByHandle(hdir1, FileRenameInfo, &renbuf1, sizeof renbuf1);
CloseHandle(hdir1);
// 第二个
hdir2 = CreateFile(TEXT("G:\\casedir_123"), GENERIC_READ | GENERIC_WRITE | DELETE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, NULL);
memset(renbuf2, 0, sizeof renbuf2);
ren2 = (FILE_RENAME_INFO*)renbuf2;
ren2->ReplaceIfExists = FALSE;
ren2->RootDirectory = NULL;
wcscpy(ren2->FileName, L"G:\\casedir");
ren2->FileNameLength = wcslen(ren2->FileName) * sizeof(wchar_t);
SetFileInformationByHandle(hdir2, FileRenameInfo, &renbuf2, sizeof renbuf2);
CloseHandle(hdir2);
// 按照区分大小写的方式查找文件/文件夹
hfind = FindFirstFileEx(TEXT("G:\\Case*"), FindExInfoStandard, &fd,
FindExSearchNameMatch, NULL, FIND_FIRST_EX_CASE_SENSITIVE);
if (hfind != INVALID_HANDLE_VALUE)
{
do
{
#ifdef UNICODE
WideCharToMultiByte(CP_ACP, 0, fd.cFileName, -1, ansipath, MAX_PATH, NULL, NULL);
#else
strcpy(ansipath, fd.cFileName);
#endif
printf("%s\n", ansipath);
} while (FindNextFile(hfind, &fd));
FindClose(hfind);
}
#if 0
// 改回来
// 第一个
hdir1 = CreateFile(TEXT("G:\\CaseDir"), GENERIC_READ | GENERIC_WRITE | DELETE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, NULL);
memset(renbuf1, 0, sizeof renbuf1);
ren1 = (FILE_RENAME_INFO*)renbuf1;
ren1->ReplaceIfExists = FALSE;
ren1->RootDirectory = NULL;
wcscpy(ren1->FileName, L"G:\\CaseDir_1");
ren1->FileNameLength = wcslen(ren1->FileName) * sizeof(wchar_t);
SetFileInformationByHandle(hdir1, FileRenameInfo, &renbuf1, sizeof renbuf1);
CloseHandle(hdir1);
// 第二个
hdir2 = CreateFile(TEXT("G:\\casedir"), GENERIC_READ | GENERIC_WRITE | DELETE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, NULL);
memset(renbuf2, 0, sizeof renbuf2);
ren2 = (FILE_RENAME_INFO*)renbuf2;
ren2->ReplaceIfExists = FALSE;
ren2->RootDirectory = NULL;
wcscpy(ren2->FileName, L"G:\\casedir_123");
ren2->FileNameLength = wcslen(ren2->FileName) * sizeof(wchar_t);
SetFileInformationByHandle(hdir2, FileRenameInfo, &renbuf2, sizeof renbuf2);
CloseHandle(hdir2);
#else
// 删掉
// 第一个
hdir1 = CreateFile(TEXT("G:\\CaseDir"), GENERIC_READ | GENERIC_WRITE | DELETE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, NULL);
del1.DeleteFile = TRUE;
SetFileInformationByHandle(hdir1, FileDispositionInfo, &del1, sizeof del1);
CloseHandle(hdir1);
// 第二个
hdir2 = CreateFile(TEXT("G:\\casedir"), GENERIC_READ | GENERIC_WRITE | DELETE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, NULL);
del2.DeleteFile = TRUE;
SetFileInformationByHandle(hdir2, FileDispositionInfo, &del2, sizeof del2);
CloseHandle(hdir2);
#endif
return 0;
}</stdio.h></windows.h>