reactos/base/shell/cmd/assoc.c
Hermès Bélusca-Maïto 3f892a8d6b
[CMD] Add missing memory allocation NULL checks (#161). CORE-8304
Adapted from a patch by Jacob S. Preciado.

Bring also the code suggestions emitted during review.
2018-08-21 14:02:24 +02:00

250 lines
6 KiB
C

/*
* Assoc.C - assoc internal command.
*
*
* History:
*
* 14-Mar-2009 Lee C. Baker
* - initial implementation
*
* 15-Mar-2009 Lee C. Baker
* - Don't write to (or use) HKEY_CLASSES_ROOT directly
* - Externalize strings
*
* TODO:
* - PrintAllAssociations might could be optimized to not fetch all registry subkeys under 'Classes', just the ones that start with '.'
* - Make sure that non-administrator users can list associations, and get appropriate error messages when they don't have sufficient
* privileges to perform an operation
*/
#include "precomp.h"
#ifdef INCLUDE_CMD_ASSOC
static INT
PrintAssociation(LPTSTR extension)
{
DWORD return_val;
HKEY hKey = NULL, hInsideKey = NULL;
DWORD fileTypeLength = 0;
LPTSTR fileType = NULL;
return_val = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Classes"), 0, KEY_READ, &hKey);
if (return_val != ERROR_SUCCESS)
return -1;
return_val = RegOpenKeyEx(hKey, extension, 0, KEY_READ, &hInsideKey);
RegCloseKey(hKey);
if (return_val != ERROR_SUCCESS)
return 0;
/* obtain string length */
return_val = RegQueryValueEx(hInsideKey, NULL, NULL, NULL, NULL, &fileTypeLength);
if (return_val == ERROR_FILE_NOT_FOUND) /* no default value, don't display */
{
RegCloseKey(hInsideKey);
return 0;
}
if (return_val != ERROR_SUCCESS)
{
RegCloseKey(hInsideKey);
return -2;
}
fileType = cmd_alloc(fileTypeLength * sizeof(TCHAR));
if (!fileType)
{
WARN("Cannot allocate memory for fileType!\n");
RegCloseKey(hInsideKey);
return -2;
}
/* obtain actual file type */
return_val = RegQueryValueEx(hInsideKey, NULL, NULL, NULL, (LPBYTE)fileType, &fileTypeLength);
RegCloseKey(hInsideKey);
if (return_val != ERROR_SUCCESS)
{
cmd_free(fileType);
return -2;
}
if (fileTypeLength != 0) /* if there is a default key, display relevant information */
{
ConOutPrintf(_T("%s=%s\n"), extension, fileType);
}
cmd_free(fileType);
return 1;
}
static INT
PrintAllAssociations(VOID)
{
DWORD return_val = 0;
HKEY hKey = NULL;
DWORD numKeys = 0;
DWORD extLength = 0;
LPTSTR extName = NULL;
DWORD keyCtr = 0;
return_val = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Classes"), 0, KEY_READ, &hKey);
if (return_val != ERROR_SUCCESS)
return -1;
return_val = RegQueryInfoKey(hKey, NULL, NULL, NULL, &numKeys, &extLength, NULL, NULL, NULL, NULL, NULL, NULL);
if (return_val != ERROR_SUCCESS)
{
RegCloseKey(hKey);
return -2;
}
extLength++;
extName = cmd_alloc(extLength * sizeof(TCHAR));
if (!extName)
{
WARN("Cannot allocate memory for extName!\n");
RegCloseKey(hKey);
return -2;
}
for (keyCtr = 0; keyCtr < numKeys; keyCtr++)
{
DWORD buffer_size = extLength;
return_val = RegEnumKeyEx(hKey, keyCtr, extName, &buffer_size, NULL, NULL, NULL, NULL);
if (return_val == ERROR_SUCCESS || return_val == ERROR_MORE_DATA)
{
if (*extName == _T('.'))
PrintAssociation(extName);
}
else
{
cmd_free(extName);
RegCloseKey(hKey);
return -1;
}
}
RegCloseKey(hKey);
cmd_free(extName);
return numKeys;
}
static INT
AddAssociation(LPTSTR extension, LPTSTR type)
{
DWORD return_val;
HKEY hKey = NULL, insideKey = NULL;
return_val = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Classes"), 0, KEY_ALL_ACCESS, &hKey);
if (return_val != ERROR_SUCCESS)
return -1;
return_val = RegCreateKeyEx(hKey, extension, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &insideKey, NULL);
RegCloseKey(hKey);
if (return_val != ERROR_SUCCESS)
return -1;
return_val = RegSetValueEx(insideKey, NULL, 0, REG_SZ, (LPBYTE)type, (_tcslen(type) + 1) * sizeof(TCHAR));
RegCloseKey(insideKey);
if (return_val != ERROR_SUCCESS)
return -2;
return 0;
}
static int
RemoveAssociation(LPTSTR extension)
{
DWORD return_val;
HKEY hKey;
return_val = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Classes"), 0, KEY_ALL_ACCESS, &hKey);
if (return_val != ERROR_SUCCESS)
return -1;
return_val = RegDeleteKey(hKey, extension);
RegCloseKey(hKey);
if (return_val != ERROR_SUCCESS)
return -2;
return 0;
}
INT CommandAssoc (LPTSTR param)
{
/* print help */
if (!_tcsncmp (param, _T("/?"), 2))
{
ConOutResPaging(TRUE,STRING_ASSOC_HELP);
return 0;
}
nErrorLevel = 0;
if (_tcslen(param) == 0)
{
PrintAllAssociations();
}
else
{
LPTSTR lpEqualSign = _tcschr(param, _T('='));
if (lpEqualSign != NULL)
{
LPTSTR fileType = lpEqualSign + 1;
LPTSTR extension = cmd_alloc((lpEqualSign - param + 1) * sizeof(TCHAR));
if (!extension)
{
WARN("Cannot allocate memory for extension!\n");
error_out_of_memory();
return 1;
}
_tcsncpy(extension, param, lpEqualSign - param);
extension[lpEqualSign - param] = _T('\0');
if (_tcslen(fileType) == 0)
/* if the equal sign is the last character
in the string, then delete the key */
{
RemoveAssociation(extension);
}
else
/* otherwise, add the key and print out the association*/
{
AddAssociation(extension, fileType);
PrintAssociation(extension);
}
cmd_free(extension);
}
else
{
/* no equal sign, print all associations */
INT retval = PrintAssociation(param);
if (retval == 0) /* if nothing printed out */
ConOutResPrintf(STRING_ASSOC_ERROR, param);
}
}
return 0;
}
#endif /* INCLUDE_CMD_ASSOC */