Windows: Use wide-character system APIs

Make CMake compile with -DUNICODE.  Make it possible for the 8 bit
encoding to eventually be UTF-8 instead ANSI.
This commit is contained in:
Clinton Stimpson 2013-12-04 22:17:24 -07:00 committed by Brad King
parent ce598cc838
commit 0b9906c2fb
9 changed files with 107 additions and 78 deletions

View File

@ -23,6 +23,7 @@
#include <cmsys/SystemTools.hxx>
#include <cmsys/Directory.hxx>
#include <cmsys/Encoding.hxx>
#include <rpc.h> // for GUID generation
@ -954,11 +955,12 @@ std::string cmCPackWIXGenerator::GenerateGUID()
UUID guid;
UuidCreate(&guid);
unsigned char *tmp = 0;
UuidToString(&guid, &tmp);
unsigned short *tmp = 0;
UuidToStringW(&guid, &tmp);
std::string result(reinterpret_cast<char*>(tmp));
RpcStringFree(&tmp);
std::string result =
cmsys::Encoding::ToNarrow(reinterpret_cast<wchar_t*>(tmp));
RpcStringFreeW(&tmp);
return cmSystemTools::UpperCase(result);
}

View File

@ -16,6 +16,7 @@
#include "cmake.h"
#include <cmsys/RegularExpression.hxx>
#include <cmsys/Encoding.hxx>
#include "cmExportBuildFileGenerator.h"
@ -252,14 +253,14 @@ void cmExportCommand::ReportRegistryError(std::string const& msg,
cmOStringStream e;
e << msg << "\n"
<< " HKEY_CURRENT_USER\\" << key << "\n";
char winmsg[1024];
if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
wchar_t winmsg[1024];
if(FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, 0, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
winmsg, 1024, 0) > 0)
{
e << "Windows reported:\n"
<< " " << winmsg;
<< " " << cmsys::Encoding::ToNarrow(winmsg);
}
this->Makefile->IssueMessage(cmake::WARNING, e.str());
}
@ -272,8 +273,9 @@ void cmExportCommand::StorePackageRegistryWin(std::string const& package,
std::string key = "Software\\Kitware\\CMake\\Packages\\";
key += package;
HKEY hKey;
LONG err = RegCreateKeyEx(HKEY_CURRENT_USER,
key.c_str(), 0, 0, REG_OPTION_NON_VOLATILE,
LONG err = RegCreateKeyExW(HKEY_CURRENT_USER,
cmsys::Encoding::ToWide(key).c_str(),
0, 0, REG_OPTION_NON_VOLATILE,
KEY_SET_VALUE, 0, &hKey, 0);
if(err != ERROR_SUCCESS)
{
@ -281,8 +283,11 @@ void cmExportCommand::StorePackageRegistryWin(std::string const& package,
"Cannot create/open registry key", key, err);
return;
}
err = RegSetValueEx(hKey, hash, 0, REG_SZ, (BYTE const*)content,
static_cast<DWORD>(strlen(content)+1));
std::wstring wcontent = cmsys::Encoding::ToWide(content);
err = RegSetValueExW(hKey, cmsys::Encoding::ToWide(hash).c_str(),
0, REG_SZ, (BYTE const*)wcontent.c_str(),
static_cast<DWORD>(wcontent.size()+1)*sizeof(wchar_t));
RegCloseKey(hKey);
if(err != ERROR_SUCCESS)
{

View File

@ -16,6 +16,8 @@
# include <cmsys/hash_map.hxx>
#endif
#include <cmsys/Encoding.hxx>
// Use a platform-specific API to get file times efficiently.
#if !defined(_WIN32) || defined(__CYGWIN__)
# define cmFileTimeComparison_Type struct stat
@ -86,7 +88,8 @@ bool cmFileTimeComparisonInternal::Stat(const char* fname,
// Windows version. Get the modification time from extended file
// attributes.
WIN32_FILE_ATTRIBUTE_DATA fdata;
if(!GetFileAttributesEx(fname, GetFileExInfoStandard, &fdata))
if(!GetFileAttributesExW(cmsys::Encoding::ToWide(fname).c_str(),
GetFileExInfoStandard, &fdata))
{
return false;
}

View File

@ -13,6 +13,7 @@
#include <cmsys/Directory.hxx>
#include <cmsys/RegularExpression.hxx>
#include <cmsys/Encoding.hxx>
#ifdef CMAKE_BUILD_WITH_CMAKE
#include "cmVariableWatch.h"
@ -1245,23 +1246,23 @@ void cmFindPackageCommand::LoadPackageRegistryWinSystem()
void cmFindPackageCommand::LoadPackageRegistryWin(bool user,
unsigned int view)
{
std::string key = "Software\\Kitware\\CMake\\Packages\\";
key += this->Name;
std::set<cmStdString> bad;
std::wstring key = L"Software\\Kitware\\CMake\\Packages\\";
key += cmsys::Encoding::ToWide(this->Name);
std::set<std::wstring> bad;
HKEY hKey;
if(RegOpenKeyEx(user? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, key.c_str(),
0, KEY_QUERY_VALUE|view, &hKey) == ERROR_SUCCESS)
if(RegOpenKeyExW(user? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, key.c_str(),
0, KEY_QUERY_VALUE|view, &hKey) == ERROR_SUCCESS)
{
DWORD valueType = REG_NONE;
char name[16384];
std::vector<char> data(512);
wchar_t name[16383]; // RegEnumValue docs limit name to 32767 _bytes_
std::vector<wchar_t> data(512);
bool done = false;
DWORD index = 0;
while(!done)
{
DWORD nameSize = static_cast<DWORD>(sizeof(name));
DWORD dataSize = static_cast<DWORD>(data.size()-1);
switch(RegEnumValue(hKey, index, name, &nameSize,
DWORD dataSize = static_cast<DWORD>(data.size()*sizeof(data[0]));
switch(RegEnumValueW(hKey, index, name, &nameSize,
0, &valueType, (BYTE*)&data[0], &dataSize))
{
case ERROR_SUCCESS:
@ -1269,7 +1270,7 @@ void cmFindPackageCommand::LoadPackageRegistryWin(bool user,
if(valueType == REG_SZ)
{
data[dataSize] = 0;
cmsys_ios::stringstream ss(&data[0]);
cmsys_ios::stringstream ss(cmsys::Encoding::ToNarrow(&data[0]));
if(!this->CheckPackageRegistryEntry(ss))
{
// The entry is invalid.
@ -1278,7 +1279,7 @@ void cmFindPackageCommand::LoadPackageRegistryWin(bool user,
}
break;
case ERROR_MORE_DATA:
data.resize(dataSize+1);
data.resize((dataSize+sizeof(data[0])-1)/sizeof(data[0]));
break;
case ERROR_NO_MORE_ITEMS: default: done = true; break;
}
@ -1288,13 +1289,13 @@ void cmFindPackageCommand::LoadPackageRegistryWin(bool user,
// Remove bad values if possible.
if(user && !bad.empty() &&
RegOpenKeyEx(HKEY_CURRENT_USER, key.c_str(),
RegOpenKeyExW(HKEY_CURRENT_USER, key.c_str(),
0, KEY_SET_VALUE|view, &hKey) == ERROR_SUCCESS)
{
for(std::set<cmStdString>::const_iterator vi = bad.begin();
for(std::set<std::wstring>::const_iterator vi = bad.begin();
vi != bad.end(); ++vi)
{
RegDeleteValue(hKey, vi->c_str());
RegDeleteValueW(hKey, vi->c_str());
}
RegCloseKey(hKey);
}

View File

@ -16,6 +16,7 @@
#include "cmLocalVisualStudio7Generator.h"
#include "cmMakefile.h"
#include "cmake.h"
#include <cmsys/Encoding.hxx>
cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator(
const char* platformName)
@ -897,11 +898,11 @@ void cmGlobalVisualStudio7Generator::CreateGUID(const char* name)
}
std::string ret;
UUID uid;
unsigned char *uidstr;
unsigned short *uidstr;
UuidCreate(&uid);
UuidToString(&uid,&uidstr);
ret = reinterpret_cast<char*>(uidstr);
RpcStringFree(&uidstr);
UuidToStringW(&uid,&uidstr);
ret = cmsys::Encoding::ToNarrow(reinterpret_cast<wchar_t*>(uidstr));
RpcStringFreeW(&uidstr);
ret = cmSystemTools::UpperCase(ret);
this->CMakeInstance->AddCacheEntry(guidStoreName.c_str(),
ret.c_str(), "Stored GUID",

View File

@ -17,6 +17,7 @@
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmTarget.h"
#include <cmsys/Encoding.hxx>
//----------------------------------------------------------------------------
cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator()
@ -559,52 +560,53 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
keyname = regKeyBase + "\\OtherProjects7";
hkey = NULL;
result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(),
0, KEY_READ, &hkey);
result = RegOpenKeyExW(HKEY_CURRENT_USER,
cmsys::Encoding::ToWide(keyname).c_str(),
0, KEY_READ, &hkey);
if (ERROR_SUCCESS == result)
{
// Iterate the subkeys and look for the values of interest in each subkey:
CHAR subkeyname[256];
DWORD cch_subkeyname = sizeof(subkeyname)/sizeof(subkeyname[0]);
CHAR keyclass[256];
DWORD cch_keyclass = sizeof(keyclass)/sizeof(keyclass[0]);
wchar_t subkeyname[256];
DWORD cch_subkeyname = sizeof(subkeyname)*sizeof(subkeyname[0]);
wchar_t keyclass[256];
DWORD cch_keyclass = sizeof(keyclass)*sizeof(keyclass[0]);
FILETIME lastWriteTime;
lastWriteTime.dwHighDateTime = 0;
lastWriteTime.dwLowDateTime = 0;
while (ERROR_SUCCESS == RegEnumKeyEx(hkey, index, subkeyname,
while (ERROR_SUCCESS == RegEnumKeyExW(hkey, index, subkeyname,
&cch_subkeyname,
0, keyclass, &cch_keyclass, &lastWriteTime))
{
// Open the subkey and query the values of interest:
HKEY hsubkey = NULL;
result = RegOpenKeyEx(hkey, subkeyname, 0, KEY_READ, &hsubkey);
result = RegOpenKeyExW(hkey, subkeyname, 0, KEY_READ, &hsubkey);
if (ERROR_SUCCESS == result)
{
DWORD valueType = REG_SZ;
CHAR data1[256];
DWORD cch_data1 = sizeof(data1)/sizeof(data1[0]);
RegQueryValueEx(hsubkey, "Path", 0, &valueType,
wchar_t data1[256];
DWORD cch_data1 = sizeof(data1)*sizeof(data1[0]);
RegQueryValueExW(hsubkey, L"Path", 0, &valueType,
(LPBYTE) &data1[0], &cch_data1);
DWORD data2 = 0;
DWORD cch_data2 = sizeof(data2);
RegQueryValueEx(hsubkey, "Security", 0, &valueType,
RegQueryValueExW(hsubkey, L"Security", 0, &valueType,
(LPBYTE) &data2, &cch_data2);
DWORD data3 = 0;
DWORD cch_data3 = sizeof(data3);
RegQueryValueEx(hsubkey, "StorageFormat", 0, &valueType,
RegQueryValueExW(hsubkey, L"StorageFormat", 0, &valueType,
(LPBYTE) &data3, &cch_data3);
s2 = cmSystemTools::LowerCase(data1);
s2 = cmSystemTools::LowerCase(cmsys::Encoding::ToNarrow(data1));
cmSystemTools::ConvertToUnixSlashes(s2);
if (s2 == s1)
{
macrosRegistered = true;
}
std::string fullname(data1);
std::string fullname = cmsys::Encoding::ToNarrow(data1);
std::string filename;
std::string filepath;
std::string filepathname;
@ -636,8 +638,8 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
}
++index;
cch_subkeyname = sizeof(subkeyname)/sizeof(subkeyname[0]);
cch_keyclass = sizeof(keyclass)/sizeof(keyclass[0]);
cch_subkeyname = sizeof(subkeyname)*sizeof(subkeyname[0]);
cch_keyclass = sizeof(keyclass)*sizeof(keyclass[0]);
lastWriteTime.dwHighDateTime = 0;
lastWriteTime.dwLowDateTime = 0;
}
@ -662,27 +664,28 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
keyname = regKeyBase + "\\RecordingProject7";
hkey = NULL;
result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(),
0, KEY_READ, &hkey);
result = RegOpenKeyExW(HKEY_CURRENT_USER,
cmsys::Encoding::ToWide(keyname).c_str(),
0, KEY_READ, &hkey);
if (ERROR_SUCCESS == result)
{
DWORD valueType = REG_SZ;
CHAR data1[256];
DWORD cch_data1 = sizeof(data1)/sizeof(data1[0]);
RegQueryValueEx(hkey, "Path", 0, &valueType,
wchar_t data1[256];
DWORD cch_data1 = sizeof(data1)*sizeof(data1[0]);
RegQueryValueExW(hkey, L"Path", 0, &valueType,
(LPBYTE) &data1[0], &cch_data1);
DWORD data2 = 0;
DWORD cch_data2 = sizeof(data2);
RegQueryValueEx(hkey, "Security", 0, &valueType,
RegQueryValueExW(hkey, L"Security", 0, &valueType,
(LPBYTE) &data2, &cch_data2);
DWORD data3 = 0;
DWORD cch_data3 = sizeof(data3);
RegQueryValueEx(hkey, "StorageFormat", 0, &valueType,
RegQueryValueExW(hkey, L"StorageFormat", 0, &valueType,
(LPBYTE) &data3, &cch_data3);
s2 = cmSystemTools::LowerCase(data1);
s2 = cmSystemTools::LowerCase(cmsys::Encoding::ToNarrow(data1));
cmSystemTools::ConvertToUnixSlashes(s2);
if (s2 == s1)
{
@ -714,24 +717,27 @@ void WriteVSMacrosFileRegistryEntry(
{
std::string keyname = regKeyBase + "\\OtherProjects7";
HKEY hkey = NULL;
LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(), 0,
LONG result = RegOpenKeyExW(HKEY_CURRENT_USER,
cmsys::Encoding::ToWide(keyname).c_str(), 0,
KEY_READ|KEY_WRITE, &hkey);
if (ERROR_SUCCESS == result)
{
// Create the subkey and set the values of interest:
HKEY hsubkey = NULL;
char lpClass[] = "";
result = RegCreateKeyEx(hkey, nextAvailableSubKeyName.c_str(), 0,
lpClass, 0, KEY_READ|KEY_WRITE, 0, &hsubkey, 0);
wchar_t lpClass[] = L"";
result = RegCreateKeyExW(hkey,
cmsys::Encoding::ToWide(nextAvailableSubKeyName).c_str(), 0,
lpClass, 0, KEY_READ|KEY_WRITE, 0, &hsubkey, 0);
if (ERROR_SUCCESS == result)
{
DWORD dw = 0;
std::string s(macrosFile);
cmSystemTools::ReplaceString(s, "/", "\\");
std::wstring ws = cmsys::Encoding::ToWide(s);
result = RegSetValueEx(hsubkey, "Path", 0, REG_SZ, (LPBYTE) s.c_str(),
static_cast<DWORD>(strlen(s.c_str()) + 1));
result = RegSetValueExW(hsubkey, L"Path", 0, REG_SZ, (LPBYTE)ws.c_str(),
static_cast<DWORD>(ws.size() + 1)*sizeof(wchar_t));
if (ERROR_SUCCESS != result)
{
std::cout << "error result 1: " << result << std::endl;
@ -741,7 +747,7 @@ void WriteVSMacrosFileRegistryEntry(
// Security value is always "1" for sample macros files (seems to be "2"
// if you put the file somewhere outside the standard VSMacros folder)
dw = 1;
result = RegSetValueEx(hsubkey, "Security",
result = RegSetValueExW(hsubkey, L"Security",
0, REG_DWORD, (LPBYTE) &dw, sizeof(DWORD));
if (ERROR_SUCCESS != result)
{
@ -751,7 +757,7 @@ void WriteVSMacrosFileRegistryEntry(
// StorageFormat value is always "0" for sample macros files
dw = 0;
result = RegSetValueEx(hsubkey, "StorageFormat",
result = RegSetValueExW(hsubkey, L"StorageFormat",
0, REG_DWORD, (LPBYTE) &dw, sizeof(DWORD));
if (ERROR_SUCCESS != result)
{

View File

@ -2224,7 +2224,7 @@ static bool cmLVS6G_IsFAT(const char* dir)
char volRoot[4] = "_:/";
volRoot[0] = dir[0];
char fsName[16];
if(GetVolumeInformation(volRoot, 0, 0, 0, 0, 0, fsName, 16) &&
if(GetVolumeInformationA(volRoot, 0, 0, 0, 0, 0, fsName, 16) &&
strstr(fsName, "FAT") != 0)
{
return true;

View File

@ -25,6 +25,7 @@
#include <cmsys/RegularExpression.hxx>
#include <cmsys/Directory.hxx>
#include <cmsys/System.h>
#include <cmsys/Encoding.hxx>
#if defined(CMAKE_BUILD_WITH_CMAKE)
# include "cmArchiveWrite.h"
# include <cm_libarchive.h>
@ -880,19 +881,23 @@ bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
Try multiple times since we may be racing against another process
creating/opening the destination file just before our MoveFileEx. */
int tries = 5;
while(!MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING) && --tries)
while(!MoveFileExW(cmsys::Encoding::ToWide(oldname).c_str(),
cmsys::Encoding::ToWide(newname).c_str(),
MOVEFILE_REPLACE_EXISTING) && --tries)
{
// Try again only if failure was due to access permissions.
if(GetLastError() != ERROR_ACCESS_DENIED)
{
return false;
}
DWORD attrs = GetFileAttributes(newname);
DWORD attrs =
GetFileAttributesW(cmsys::Encoding::ToWide(newname).c_str());
if((attrs != INVALID_FILE_ATTRIBUTES) &&
(attrs & FILE_ATTRIBUTE_READONLY))
{
// Remove the read-only attribute from the destination file.
SetFileAttributes(newname, attrs & ~FILE_ATTRIBUTE_READONLY);
SetFileAttributesW(cmsys::Encoding::ToWide(newname).c_str(),
attrs & ~FILE_ATTRIBUTE_READONLY);
}
else
{
@ -1884,10 +1889,12 @@ bool cmSystemTools::CopyFileTime(const char* fromFile, const char* toFile)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
cmSystemToolsWindowsHandle hFrom =
CreateFile(fromFile, GENERIC_READ, FILE_SHARE_READ, 0,
OPEN_EXISTING, 0, 0);
CreateFileW(cmsys::Encoding::ToWide(fromFile).c_str(),
GENERIC_READ, FILE_SHARE_READ, 0,
OPEN_EXISTING, 0, 0);
cmSystemToolsWindowsHandle hTo =
CreateFile(toFile, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
CreateFileW(cmsys::Encoding::ToWide(toFile).c_str(),
GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if(!hFrom || !hTo)
{
return false;
@ -1938,7 +1945,8 @@ bool cmSystemTools::FileTimeGet(const char* fname, cmSystemToolsFileTime* t)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
cmSystemToolsWindowsHandle h =
CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
CreateFileW(cmsys::Encoding::ToWide(fname).c_str(),
GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if(!h)
{
return false;
@ -1964,7 +1972,8 @@ bool cmSystemTools::FileTimeSet(const char* fname, cmSystemToolsFileTime* t)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
cmSystemToolsWindowsHandle h =
CreateFile(fname, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
CreateFileW(cmsys::Encoding::ToWide(fname).c_str(),
GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if(!h)
{
return false;
@ -2059,9 +2068,10 @@ void cmSystemTools::FindCMakeResources(const char* argv0)
std::string exe_dir;
#if defined(_WIN32) && !defined(__CYGWIN__)
(void)argv0; // ignore this on windows
char modulepath[_MAX_PATH];
::GetModuleFileName(NULL, modulepath, sizeof(modulepath));
exe_dir = cmSystemTools::GetFilenamePath(modulepath);
wchar_t modulepath[_MAX_PATH];
::GetModuleFileNameW(NULL, modulepath, sizeof(modulepath));
exe_dir =
cmSystemTools::GetFilenamePath(cmsys::Encoding::ToNarrow(modulepath));
#elif defined(__APPLE__)
(void)argv0; // ignore this on OS X
# define CM_EXE_PATH_LOCAL_SIZE 16384

View File

@ -23,6 +23,7 @@
#include <windows.h>
#include <sstream>
#include <cmSystemTools.h>
#include <cmsys/Encoding.hxx>
// We don't want any wildcard expansion.
// See http://msdn.microsoft.com/en-us/library/zay8tzh6(v=vs.85).aspx
@ -100,7 +101,7 @@ static std::string getArg(std::string& cmdline) {
return ret;
}
static void parseCommandLine(LPTSTR wincmdline,
static void parseCommandLine(LPWSTR wincmdline,
std::string& lang,
std::string& srcfile,
std::string& dfile,
@ -109,7 +110,7 @@ static void parseCommandLine(LPTSTR wincmdline,
std::string& clpath,
std::string& binpath,
std::string& rest) {
std::string cmdline(wincmdline);
std::string cmdline = cmsys::Encoding::ToNarrow(wincmdline);
/* self */ getArg(cmdline);
lang = getArg(cmdline);
srcfile = getArg(cmdline);
@ -247,7 +248,7 @@ int main() {
// the same command line verbatim.
std::string lang, srcfile, dfile, objfile, prefix, cl, binpath, rest;
parseCommandLine(GetCommandLine(), lang, srcfile, dfile, objfile,
parseCommandLine(GetCommandLineW(), lang, srcfile, dfile, objfile,
prefix, cl, binpath, rest);
// needed to suppress filename output of msvc tools