Index: config.h
===================================================================
--- config.h (revision 39998)
+++ config.h (working copy)
@@ -50,6 +50,7 @@
#ifdef NT4_INTERNAL_COMMANDS
#define INCLUDE_CMD_ACTIVATE
#endif
+#define INCLUDE_CMD_ASSOC
#define INCLUDE_CMD_ATTRIB
#define INCLUDE_CMD_CHCP
#define INCLUDE_CMD_CHDIR
Index: cmd.rbuild
===================================================================
--- cmd.rbuild (revision 39998)
+++ cmd.rbuild (working copy)
@@ -16,6 +16,7 @@
precomp.h
alias.c
+ assoc.c
attrib.c
batch.c
beep.c
Index: cmdtable.c
===================================================================
--- cmdtable.c (revision 39998)
+++ cmdtable.c (working copy)
@@ -37,6 +37,10 @@
{_T("alias"), 0, CommandAlias},
#endif
+#ifdef INCLUDE_CMD_ASSOC
+ {_T("assoc"), 0, CommandAssoc},
+#endif
+
#ifdef INCLUDE_CMD_ATTRIB
{_T("attrib"), 0, CommandAttrib},
#endif
Index: cmd.h
===================================================================
--- cmd.h (revision 39998)
+++ cmd.h (working copy)
@@ -71,6 +71,9 @@
VOID ExpandAlias (LPTSTR, INT);
INT CommandAlias (LPTSTR);
+/* Prototypes for ASSOC.C */
+INT CommandAssoc (LPTSTR);
+
/* Prototypes for ATTRIB.C */
INT CommandAttrib (LPTSTR);
Index: assoc.c
===================================================================
--- assoc.c (revision 0)
+++ assoc.c (revision 0)
@@ -0,0 +1,275 @@
+/*
+ * Assoc.C - assoc internal command.
+ *
+ *
+ * History:
+ *
+ * 14-Mar-2009 Lee C. Baker
+ * initial implementation
+ *
+ * TODO:
+ * - PrintAllAssociations might could be optimized to not fetch all registry subkeys under HKEY_CLASSES_ROOT, just the ones that start with '.'
+ * - Externalize 'help' string
+ */
+
+#include
+#include
+
+#ifdef INCLUDE_CMD_ASSOC
+
+
+static INT
+PrintAssociation(LPTSTR extension)
+{
+ DWORD return_val;
+ HKEY hKey;
+
+ DWORD fileTypeLength = 0;
+ LPTSTR fileType = NULL;
+
+ return_val = RegCreateKeyEx(HKEY_CLASSES_ROOT, extension, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
+
+ if(return_val != ERROR_SUCCESS)
+ {
+ RegCloseKey(hKey);
+ return -1;
+ }
+
+ return_val = RegQueryValueEx(hKey, NULL, NULL, NULL, NULL, &fileTypeLength);
+
+ if(return_val == ERROR_FILE_NOT_FOUND) /* no default value, don't display */
+ {
+ RegCloseKey(hKey);
+ return 0;
+ }
+
+ if(return_val != ERROR_SUCCESS)
+ {
+ RegCloseKey(hKey);
+ return -2;
+ }
+
+ fileType = cmd_alloc(fileTypeLength * sizeof(TCHAR));
+
+ return_val = RegQueryValueEx(hKey, NULL, NULL, NULL, (LPBYTE) fileType, &fileTypeLength);
+
+ RegCloseKey(hKey);
+
+ 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\r\n"), extension, fileType);
+ }
+
+ if(fileTypeLength)
+ cmd_free(fileType);
+
+ return 0;
+}
+
+static INT
+PrintAllAssociations()
+{
+ DWORD return_val = 0;
+ HKEY hKey = NULL;
+ DWORD numKeys = 0;
+
+ DWORD extLength = 0;
+ LPTSTR extName = NULL;
+ DWORD keyCtr = 0;
+
+ return_val = RegCreateKeyEx(HKEY_CLASSES_ROOT, _T(""), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
+
+ if(return_val != ERROR_SUCCESS)
+ {
+ RegCloseKey(hKey);
+ 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;
+ }
+
+ extName = cmd_alloc(extLength * sizeof(TCHAR));
+
+ 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);
+
+ if(extName)
+ cmd_free(extName);
+
+ return numKeys;
+}
+
+static INT
+AddAssociation(LPTSTR extension, LPTSTR type)
+{
+ DWORD return_val;
+ HKEY hKey = NULL, insideKey = NULL;
+
+ return_val = RegCreateKeyEx(HKEY_CLASSES_ROOT, extension, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
+
+ if(return_val != ERROR_SUCCESS)
+ return -1;
+
+ return_val = RegSetValueEx(hKey, NULL, 0, REG_SZ, (LPBYTE)type, (_tcslen(type) + 1) * sizeof(TCHAR));
+
+ if(return_val != ERROR_SUCCESS)
+ {
+ RegCloseKey(hKey);
+ return -2;
+ }
+
+ RegCloseKey(hKey);
+
+ return_val = RegCreateKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Classes"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
+
+ if(return_val != ERROR_SUCCESS)
+ return -1;
+
+ return_val = RegCreateKeyEx(hKey, extension, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &insideKey, NULL);
+
+ if(return_val != ERROR_SUCCESS)
+ {
+ RegCloseKey(hKey);
+ return -1;
+ }
+
+ return_val = RegSetValueEx(insideKey, NULL, 0, REG_SZ, (LPBYTE)type, (_tcslen(type) + 1) * sizeof(TCHAR));
+
+ if(return_val != ERROR_SUCCESS)
+ {
+ RegCloseKey(insideKey);
+ RegCloseKey(hKey);
+ return -2;
+ }
+
+ RegCloseKey(insideKey);
+ RegCloseKey(hKey);
+ return 0;
+}
+
+
+static int
+RemoveAssociation(LPTSTR extension)
+{
+ DWORD return_val;
+ HKEY hKey;
+
+ return_val = RegCreateKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Classes"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
+
+ if(return_val != ERROR_SUCCESS)
+ return -1;
+
+ return_val = RegDeleteKey(hKey, extension);
+
+ if(return_val != ERROR_SUCCESS)
+ {
+ RegCloseKey(hKey);
+ return -2;
+ }
+
+ return_val = RegDeleteKey(HKEY_CLASSES_ROOT, extension);
+
+ if(return_val != ERROR_SUCCESS)
+ {
+ RegCloseKey(hKey);
+ return -3;
+ }
+
+ RegCloseKey(hKey);
+ return 0;
+}
+
+
+
+INT CommandAssoc (LPTSTR param)
+{
+
+ LPTSTR lpEqualSign = NULL;
+
+ /* print help */
+ if (!_tcsncmp (param, _T("/?"), 2))
+ {
+ //TODO figure out how to create string resources
+/* ConOutResPaging(TRUE,STRING_ASSOC_HELP); */
+ ConOutPuts(
+ _T("Modify file extension associations.\r\n"
+ "assoc [.ext[=[FileType]]]\r\n"
+ "\r\n"
+ "assoc (print all associations)\r\n"
+ "assoc .ext (print specific association)\r\n"
+ "assoc .ext= (remove specific association)\r\n"
+ "assoc .ext=FileType (add new association)\r\n"
+ ));
+
+ return 0;
+ }
+
+ nErrorLevel = 0;
+
+ if(_tcslen(param) == 0)
+ PrintAllAssociations();
+ else
+ {
+ lpEqualSign = _tcschr(param, _T('='));
+ if(lpEqualSign != NULL)
+ {
+ LPTSTR fileType = lpEqualSign + 1;
+ LPTSTR extension = cmd_alloc((lpEqualSign - param + 1) * sizeof(TCHAR));
+
+ _tcsncpy(extension, param, lpEqualSign - param);
+ extension[lpEqualSign - param] = (TCHAR)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 */
+ PrintAssociation(param);
+ }
+ }
+
+ return 0;
+}
+
+#endif /* INCLUDE_CMD_ASSOC */