* fhandler.h (fhandler_registry::value_name): Convert to wchar_t*.
* fhandler_registry.cc: Call UNICODE registry functions throughout and convert to multibyte using current locale's charset. Accommodate throughout. (must_encode): Take wchar_t. (encode_regname): Convert from wchar_t *. (decode_regname): Convert to wchar_t *.
This commit is contained in:
		| @@ -1,3 +1,13 @@ | ||||
| 2009-12-18  Corinna Vinschen  <corinna@vinschen.de> | ||||
|  | ||||
| 	* fhandler.h (fhandler_registry::value_name): Convert to wchar_t*. | ||||
| 	* fhandler_registry.cc: Call UNICODE registry functions throughout | ||||
| 	and convert to multibyte using current locale's charset.  Accommodate | ||||
| 	throughout. | ||||
| 	(must_encode): Take wchar_t. | ||||
| 	(encode_regname): Convert from wchar_t *. | ||||
| 	(decode_regname): Convert to wchar_t *. | ||||
|  | ||||
| 2009-12-18  Corinna Vinschen  <corinna@vinschen.de> | ||||
|  | ||||
| 	* path.sgml (func-cygwin-conv-path): Clarify meaning of size parameter. | ||||
|   | ||||
| @@ -1349,7 +1349,7 @@ class fhandler_netdrive: public fhandler_virtual | ||||
| class fhandler_registry: public fhandler_proc | ||||
| { | ||||
|  private: | ||||
|   char *value_name; | ||||
|   wchar_t *value_name; | ||||
|   DWORD wow64; | ||||
|   int prefix_len; | ||||
|  public: | ||||
|   | ||||
| @@ -96,16 +96,16 @@ static HKEY open_key (const char *name, REGSAM access, DWORD wow64, bool isValue | ||||
| /* Return true if char must be encoded. | ||||
|  */ | ||||
| static inline bool | ||||
| must_encode (char c) | ||||
| must_encode (wchar_t c) | ||||
| { | ||||
|   return (isdirsep (c) || c == ':' || c == '%'); | ||||
|   return (iswdirsep (c) || c == L':' || c == L'%'); | ||||
| } | ||||
|  | ||||
| /* Encode special chars in registry key or value name. | ||||
|  * Returns 0: success, -1: error. | ||||
|  */ | ||||
| static int | ||||
| encode_regname (char * dst, const char * src, bool add_val) | ||||
| encode_regname (char *dst, const wchar_t *src, bool add_val) | ||||
| { | ||||
|   int di = 0; | ||||
|   if (!src[0]) | ||||
| @@ -113,10 +113,11 @@ encode_regname (char * dst, const char * src, bool add_val) | ||||
|   else | ||||
|     for (int si = 0; src[si]; si++) | ||||
|       { | ||||
| 	char c = src[si]; | ||||
| 	wchar_t c = src[si]; | ||||
| 	if (must_encode (c) || | ||||
| 	    (si == 0 && ((c == '.' && (!src[1] || (src[1] == '.' && !src[2]))) || | ||||
| 			(c == '@' && !src[1])))) | ||||
| 	    (si == 0 && ((c == L'.' | ||||
| 			  && (!src[1] || (src[1] == L'.' && !src[2]))) | ||||
| 			 || (c == L'@' && !src[1])))) | ||||
| 	  { | ||||
| 	    if (di + 3 >= NAME_MAX + 1) | ||||
| 	      return -1; | ||||
| @@ -124,7 +125,7 @@ encode_regname (char * dst, const char * src, bool add_val) | ||||
| 	    di += 3; | ||||
| 	  } | ||||
| 	else | ||||
| 	  dst[di++] = c; | ||||
| 	  di += sys_wcstombs (dst + di, NAME_MAX + 1 - di, &c, 1); | ||||
|       } | ||||
|  | ||||
|   if (add_val) | ||||
| @@ -143,12 +144,13 @@ encode_regname (char * dst, const char * src, bool add_val) | ||||
|  * Returns 0: success, 1: "%val" detected, -1: error. | ||||
|  */ | ||||
| static int | ||||
| decode_regname (char * dst, const char * src, int len = -1) | ||||
| decode_regname (wchar_t *wdst, const char *src, int len = -1) | ||||
| { | ||||
|   if (len < 0) | ||||
|     len = strlen (src); | ||||
|  | ||||
|   char dst[len + 1]; | ||||
|   int res = 0; | ||||
|  | ||||
|   if (len > 4 && !memcmp (src + len - 4, "%val", 4)) | ||||
|     { | ||||
|       len -= 4; | ||||
| @@ -169,7 +171,7 @@ decode_regname (char * dst, const char * src, int len = -1) | ||||
| 	    char s[] = {src[si+1], src[si+2], '\0'}; | ||||
| 	    char *p; | ||||
| 	    c = strtoul (s, &p, 16); | ||||
| 	    if (!(must_encode (c) || | ||||
| 	    if (!(must_encode ((wchar_t) c) || | ||||
| 		  (si == 0 && ((c == '.' && (len == 3 || (src[3] == '.' && len == 4))) || | ||||
| 			       (c == '@' && len == 3))))) | ||||
| 	      return -1; | ||||
| @@ -181,6 +183,7 @@ decode_regname (char * dst, const char * src, int len = -1) | ||||
|       } | ||||
|  | ||||
|   dst[di] = 0; | ||||
|   sys_mbstowcs (wdst, NAME_MAX + 1, dst); | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| @@ -216,10 +219,10 @@ private: | ||||
| /* Return true if subkey NAME exists in key PARENT. | ||||
|  */ | ||||
| static bool | ||||
| key_exists (HKEY parent, const char * name, DWORD wow64) | ||||
| key_exists (HKEY parent, const wchar_t *name, DWORD wow64) | ||||
| { | ||||
|   HKEY hKey = (HKEY) INVALID_HANDLE_VALUE; | ||||
|   LONG error = RegOpenKeyEx (parent, name, 0, KEY_READ | wow64, &hKey); | ||||
|   LONG error = RegOpenKeyExW (parent, name, 0, KEY_READ | wow64, &hKey); | ||||
|   if (error == ERROR_SUCCESS) | ||||
|     RegCloseKey (hKey); | ||||
|  | ||||
| @@ -239,7 +242,7 @@ fhandler_registry::exists () | ||||
|   int file_type = 0, index = 0, pathlen; | ||||
|   DWORD buf_size = NAME_MAX + 1; | ||||
|   LONG error; | ||||
|   char buf[buf_size]; | ||||
|   wchar_t buf[buf_size]; | ||||
|   const char *file; | ||||
|   HKEY hKey = (HKEY) INVALID_HANDLE_VALUE; | ||||
|  | ||||
| @@ -273,7 +276,7 @@ fhandler_registry::exists () | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       char dec_file[NAME_MAX + 1]; | ||||
|       wchar_t dec_file[NAME_MAX + 1]; | ||||
|  | ||||
|       int val_only = decode_regname (dec_file, file); | ||||
|       if (val_only < 0) | ||||
| @@ -310,11 +313,11 @@ fhandler_registry::exists () | ||||
| 	  if (!val_only && dec_file[0]) | ||||
| 	    { | ||||
| 	      while (ERROR_SUCCESS == | ||||
| 		     (error = RegEnumKeyEx (hKey, index++, buf, &buf_size, | ||||
| 					    NULL, NULL, NULL, NULL)) | ||||
| 		     (error = RegEnumKeyExW (hKey, index++, buf, &buf_size, | ||||
| 					     NULL, NULL, NULL, NULL)) | ||||
| 		     || (error == ERROR_MORE_DATA)) | ||||
| 		{ | ||||
| 		  if (strcasematch (buf, dec_file)) | ||||
| 		  if (!wcscasecmp (buf, dec_file)) | ||||
| 		    { | ||||
| 		      file_type = 1; | ||||
| 		      goto out; | ||||
| @@ -331,11 +334,11 @@ fhandler_registry::exists () | ||||
| 	    } | ||||
|  | ||||
| 	  while (ERROR_SUCCESS == | ||||
| 		 (error = RegEnumValue (hKey, index++, buf, &buf_size, NULL, NULL, | ||||
| 					NULL, NULL)) | ||||
| 		 (error = RegEnumValueW (hKey, index++, buf, &buf_size, | ||||
| 					 NULL, NULL, NULL, NULL)) | ||||
| 		 || (error == ERROR_MORE_DATA)) | ||||
| 	    { | ||||
| 	      if (strcasematch (buf, dec_file)) | ||||
| 	      if (!wcscasecmp (buf, dec_file)) | ||||
| 		{ | ||||
| 		  file_type = -1; | ||||
| 		  goto out; | ||||
| @@ -437,12 +440,28 @@ fhandler_registry::fstat (struct __stat64 *buf) | ||||
| 		  while (!isdirsep (*value_name)) | ||||
| 		    value_name--; | ||||
| 		  value_name++; | ||||
| 		  char dec_value_name[NAME_MAX + 1]; | ||||
| 		  DWORD dwSize; | ||||
| 		  if (decode_regname (dec_value_name, value_name) >= 0 && | ||||
| 		      ERROR_SUCCESS == | ||||
| 		      RegQueryValueEx (hKey, dec_value_name, NULL, NULL, NULL, | ||||
| 				       &dwSize)) | ||||
| 		  wchar_t dec_value_name[NAME_MAX + 1]; | ||||
| 		  DWORD dwSize = 0; | ||||
| 		  DWORD type; | ||||
| 		  if (decode_regname (dec_value_name, value_name) >= 0 | ||||
| 		      && RegQueryValueExW (hKey, dec_value_name, NULL, &type, | ||||
| 					   NULL, &dwSize) == ERROR_SUCCESS | ||||
| 		      && (type == REG_SZ || type == REG_EXPAND_SZ | ||||
| 			  || type == REG_MULTI_SZ || type == REG_LINK)) | ||||
| 		    { | ||||
| 		      PBYTE tmpbuf = (PBYTE) malloc (dwSize); | ||||
| 		      if (!tmpbuf | ||||
| 			  || RegQueryValueExW (hKey, dec_value_name, | ||||
| 					       NULL, NULL, tmpbuf, &dwSize) | ||||
| 			     != ERROR_SUCCESS) | ||||
| 			buf->st_size = dwSize / sizeof (wchar_t); | ||||
| 		      else | ||||
| 			buf->st_size = sys_wcstombs (NULL, 0, | ||||
| 						     (wchar_t *) tmpbuf, | ||||
| 						     dwSize / sizeof (wchar_t)); | ||||
| 		      free (tmpbuf); | ||||
| 		    } | ||||
| 		  else | ||||
| 		    buf->st_size = dwSize; | ||||
| 		} | ||||
| 	      __uid32_t uid; | ||||
| @@ -481,7 +500,7 @@ int | ||||
| fhandler_registry::readdir (DIR *dir, dirent *de) | ||||
| { | ||||
|   DWORD buf_size = NAME_MAX + 1; | ||||
|   char buf[buf_size]; | ||||
|   wchar_t buf[buf_size]; | ||||
|   HANDLE handle; | ||||
|   const char *path = dir->__d_dirname + proc_len + 1 + prefix_len; | ||||
|   LONG error; | ||||
| @@ -529,14 +548,14 @@ retry: | ||||
|     /* For the moment, the type of key is ignored here. when write access is added, | ||||
|      * maybe add an extension for the type of each value? | ||||
|      */ | ||||
|     error = RegEnumValue ((HKEY) dir->__handle, | ||||
| 			  (dir->__d_position & ~REG_ENUM_VALUES_MASK) >> 16, | ||||
| 			  buf, &buf_size, NULL, NULL, NULL, NULL); | ||||
|     error = RegEnumValueW ((HKEY) dir->__handle, | ||||
| 			   (dir->__d_position & ~REG_ENUM_VALUES_MASK) >> 16, | ||||
| 			   buf, &buf_size, NULL, NULL, NULL, NULL); | ||||
|   else | ||||
|     error = | ||||
|       RegEnumKeyEx ((HKEY) dir->__handle, dir->__d_position - | ||||
| 		    SPECIAL_DOT_FILE_COUNT, buf, &buf_size, NULL, NULL, NULL, | ||||
| 		    NULL); | ||||
|       RegEnumKeyExW ((HKEY) dir->__handle, dir->__d_position - | ||||
| 		     SPECIAL_DOT_FILE_COUNT, buf, &buf_size, | ||||
| 		     NULL, NULL, NULL, NULL); | ||||
|   if (error == ERROR_NO_MORE_ITEMS | ||||
|       && (dir->__d_position & REG_ENUM_VALUES_MASK) == 0) | ||||
|     { | ||||
| @@ -727,7 +746,7 @@ fhandler_registry::open (int flags, mode_t mode) | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       char dec_file[NAME_MAX + 1]; | ||||
|       wchar_t dec_file[NAME_MAX + 1]; | ||||
|       int val_only = decode_regname (dec_file, file); | ||||
|       if (val_only < 0) | ||||
| 	{ | ||||
| @@ -752,7 +771,7 @@ fhandler_registry::open (int flags, mode_t mode) | ||||
| 	flags |= O_DIROPEN; | ||||
|  | ||||
|       set_io_handle (handle); | ||||
|       value_name = cstrdup (dec_file); | ||||
|       value_name = cwcsdup (dec_file); | ||||
|  | ||||
|       if (!(flags & O_DIROPEN) && !fill_filebuf ()) | ||||
| 	{ | ||||
| @@ -809,7 +828,7 @@ fhandler_registry::fill_filebuf () | ||||
|  | ||||
|   if (handle != HKEY_PERFORMANCE_DATA) | ||||
|     { | ||||
|       error = RegQueryValueEx (handle, value_name, NULL, &type, NULL, &size); | ||||
|       error = RegQueryValueExW (handle, value_name, NULL, &type, NULL, &size); | ||||
|       if (error != ERROR_SUCCESS) | ||||
| 	{ | ||||
| 	  if (error != ERROR_FILE_NOT_FOUND) | ||||
| @@ -819,17 +838,28 @@ fhandler_registry::fill_filebuf () | ||||
| 	    } | ||||
| 	  goto value_not_found; | ||||
| 	} | ||||
|       bufalloc = size; | ||||
|       filebuf = (char *) cmalloc_abort (HEAP_BUF, bufalloc); | ||||
|       PBYTE tmpbuf = (PBYTE) cmalloc_abort (HEAP_BUF, size); | ||||
|       error = | ||||
| 	RegQueryValueEx (handle, value_name, NULL, NULL, (BYTE *) filebuf, | ||||
| 			 &size); | ||||
| 	RegQueryValueExW (handle, value_name, NULL, NULL, tmpbuf, &size); | ||||
|       if (error != ERROR_SUCCESS) | ||||
| 	{ | ||||
| 	  seterrno_from_win_error (__FILE__, __LINE__, error); | ||||
| 	  return true; | ||||
| 	} | ||||
|       filesize = size; | ||||
|       if (type == REG_SZ || type == REG_EXPAND_SZ || type == REG_MULTI_SZ | ||||
| 	  || type == REG_LINK) | ||||
| 	bufalloc = sys_wcstombs (NULL, 0, (wchar_t *) tmpbuf, | ||||
| 				 size / sizeof (wchar_t)); | ||||
|       else | ||||
| 	bufalloc = size; | ||||
|       filebuf = (char *) cmalloc_abort (HEAP_BUF, bufalloc); | ||||
|       if (type == REG_SZ || type == REG_EXPAND_SZ || type == REG_MULTI_SZ | ||||
| 	  || type == REG_LINK) | ||||
| 	sys_wcstombs (filebuf, bufalloc, (wchar_t *) tmpbuf, | ||||
| 		      size / sizeof (wchar_t)); | ||||
|       else | ||||
| 	memcpy (filebuf, tmpbuf, bufalloc); | ||||
|       filesize = bufalloc; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
| @@ -839,8 +869,8 @@ fhandler_registry::fill_filebuf () | ||||
| 	  bufalloc += 16 * 1024; | ||||
| 	  filebuf = (char *) crealloc_abort (filebuf, bufalloc); | ||||
| 	  size = bufalloc; | ||||
| 	  error = RegQueryValueEx (handle, value_name, NULL, &type, | ||||
| 				   (BYTE *) filebuf, &size); | ||||
| 	  error = RegQueryValueExW (handle, value_name, NULL, &type, | ||||
| 				    (PBYTE) filebuf, &size); | ||||
| 	  if (error != ERROR_SUCCESS && error != ERROR_MORE_DATA) | ||||
| 	    { | ||||
| 	      seterrno_from_win_error (__FILE__, __LINE__, error); | ||||
| @@ -855,13 +885,13 @@ fhandler_registry::fill_filebuf () | ||||
|   return true; | ||||
| value_not_found: | ||||
|   DWORD buf_size = NAME_MAX + 1; | ||||
|   char buf[buf_size]; | ||||
|   wchar_t buf[buf_size]; | ||||
|   int index = 0; | ||||
|   while (ERROR_SUCCESS == | ||||
| 	 (error = RegEnumKeyEx (handle, index++, buf, &buf_size, NULL, NULL, | ||||
| 				NULL, NULL)) || (error == ERROR_MORE_DATA)) | ||||
| 	 (error = RegEnumKeyExW (handle, index++, buf, &buf_size, NULL, NULL, | ||||
| 				 NULL, NULL)) || (error == ERROR_MORE_DATA)) | ||||
|     { | ||||
|       if (strcasematch (buf, value_name)) | ||||
|       if (!wcscasecmp (buf, value_name)) | ||||
| 	{ | ||||
| 	  set_errno (EISDIR); | ||||
| 	  return false; | ||||
| @@ -884,7 +914,7 @@ open_key (const char *name, REGSAM access, DWORD wow64, bool isValue) | ||||
|   HKEY hKey = (HKEY) INVALID_HANDLE_VALUE; | ||||
|   HKEY hParentKey = (HKEY) INVALID_HANDLE_VALUE; | ||||
|   bool parentOpened = false; | ||||
|   char component[NAME_MAX + 1]; | ||||
|   wchar_t component[NAME_MAX + 1]; | ||||
|  | ||||
|   while (*name) | ||||
|     { | ||||
| @@ -919,13 +949,13 @@ open_key (const char *name, REGSAM access, DWORD wow64, bool isValue) | ||||
| 	  REGSAM effective_access = KEY_READ; | ||||
| 	  if ((strchr (name, '/') == NULL && isValue == true) || *name == 0) | ||||
| 	    effective_access = access; | ||||
| 	  LONG error = RegOpenKeyEx (hParentKey, component, 0, | ||||
| 				     effective_access | wow64, &hKey); | ||||
| 	  LONG error = RegOpenKeyExW (hParentKey, component, 0, | ||||
| 				      effective_access | wow64, &hKey); | ||||
| 	  if (error == ERROR_ACCESS_DENIED) /* Try opening with backup intent */ | ||||
| 	    error = RegCreateKeyEx (hParentKey, component, 0, NULL, | ||||
| 				    REG_OPTION_BACKUP_RESTORE, | ||||
| 				    effective_access | wow64, NULL, | ||||
| 				    &hKey, NULL); | ||||
| 	    error = RegCreateKeyExW (hParentKey, component, 0, NULL, | ||||
| 				     REG_OPTION_BACKUP_RESTORE, | ||||
| 				     effective_access | wow64, NULL, | ||||
| 				     &hKey, NULL); | ||||
| 	  if (parentOpened) | ||||
| 	    RegCloseKey (hParentKey); | ||||
| 	  if (error != ERROR_SUCCESS) | ||||
| @@ -940,7 +970,7 @@ open_key (const char *name, REGSAM access, DWORD wow64, bool isValue) | ||||
|       else | ||||
| 	{ | ||||
| 	  for (int i = 0; registry_listing[i]; i++) | ||||
| 	    if (strcasematch (component, registry_listing[i])) | ||||
| 	    if (strncasematch (anchor, registry_listing[i], name - anchor - 1)) | ||||
| 	      hKey = registry_keys[i]; | ||||
| 	  if (hKey == (HKEY) INVALID_HANDLE_VALUE) | ||||
| 	    return hKey; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user