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 */