From ef4415728b6e3129259aebe5fc8829f89a606237 Mon Sep 17 00:00:00 2001 From: Jeffrey Morlan Date: Tue, 17 Mar 2009 22:27:33 +0000 Subject: [PATCH] - Implement MKLINK command. - Remove unused library shell32 from cmd.rbuild. svn path=/trunk/; revision=40082 --- reactos/base/shell/cmd/cmd.h | 4 + reactos/base/shell/cmd/cmd.rbuild | 2 +- reactos/base/shell/cmd/cmdtable.c | 4 + reactos/base/shell/cmd/config.h | 1 + reactos/base/shell/cmd/lang/de-DE.rc | 11 ++ reactos/base/shell/cmd/lang/el-GR.rc | 11 ++ reactos/base/shell/cmd/lang/en-US.rc | 11 ++ reactos/base/shell/cmd/lang/es-ES.rc | 11 ++ reactos/base/shell/cmd/lang/fr-FR.rc | 11 ++ reactos/base/shell/cmd/lang/hu-HU.rc | 11 ++ reactos/base/shell/cmd/lang/id-ID.rc | 11 ++ reactos/base/shell/cmd/lang/it-IT.rc | 11 ++ reactos/base/shell/cmd/lang/ja-JP.rc | 11 ++ reactos/base/shell/cmd/lang/no-NO.rc | 11 ++ reactos/base/shell/cmd/lang/pl-PL.rc | 11 ++ reactos/base/shell/cmd/lang/ru-RU.rc | 11 ++ reactos/base/shell/cmd/lang/uk-UA.rc | 11 ++ reactos/base/shell/cmd/mklink.c | 219 +++++++++++++++++++++++++++ reactos/base/shell/cmd/resource.h | 4 + 19 files changed, 376 insertions(+), 1 deletion(-) create mode 100644 reactos/base/shell/cmd/mklink.c diff --git a/reactos/base/shell/cmd/cmd.h b/reactos/base/shell/cmd/cmd.h index 7184d53a020..e4013ad3089 100644 --- a/reactos/base/shell/cmd/cmd.h +++ b/reactos/base/shell/cmd/cmd.h @@ -320,6 +320,10 @@ extern UINT OutputCodePage; INT CommandMemory (LPTSTR); +/* Prototypes for MKLINK.C */ +INT cmd_mklink(LPTSTR); + + /* Prototypes for MISC.C */ INT GetRootPath(TCHAR *InPath,TCHAR *OutPath,INT size); BOOL SetRootPath(TCHAR *InPath); diff --git a/reactos/base/shell/cmd/cmd.rbuild b/reactos/base/shell/cmd/cmd.rbuild index 2a3dfc03ac2..dc56ebf9dd2 100644 --- a/reactos/base/shell/cmd/cmd.rbuild +++ b/reactos/base/shell/cmd/cmd.rbuild @@ -9,7 +9,6 @@ wine kernel32 advapi32 - shell32 user32 cmd.rc main.c @@ -49,6 +48,7 @@ locale.c memory.c misc.c + mklink.c move.c msgbox.c parser.c diff --git a/reactos/base/shell/cmd/cmdtable.c b/reactos/base/shell/cmd/cmdtable.c index 40558042981..c26407f1f2b 100644 --- a/reactos/base/shell/cmd/cmdtable.c +++ b/reactos/base/shell/cmd/cmdtable.c @@ -139,6 +139,10 @@ COMMAND cmds[] = {_T("mkdir"), CMD_SPECIAL, cmd_mkdir}, #endif +#ifdef INCLUDE_CMD_MKLINK + {_T("mklink"), 0, cmd_mklink}, +#endif + #ifdef INCLUDE_CMD_MOVE {_T("move"), 0, cmd_move}, #endif diff --git a/reactos/base/shell/cmd/config.h b/reactos/base/shell/cmd/config.h index f206d91566f..18e3093bfff 100644 --- a/reactos/base/shell/cmd/config.h +++ b/reactos/base/shell/cmd/config.h @@ -66,6 +66,7 @@ #define INCLUDE_CMD_LABEL #define INCLUDE_CMD_MEMORY #define INCLUDE_CMD_MKDIR +#define INCLUDE_CMD_MKLINK #define INCLUDE_CMD_MOVE #ifdef NT4_INTERNAL_COMMANDS #define INCLUDE_CMD_MSGBOX diff --git a/reactos/base/shell/cmd/lang/de-DE.rc b/reactos/base/shell/cmd/lang/de-DE.rc index 4d5318dc694..77efbc59ec0 100644 --- a/reactos/base/shell/cmd/lang/de-DE.rc +++ b/reactos/base/shell/cmd/lang/de-DE.rc @@ -294,6 +294,13 @@ STRING_LOCALE_HELP1, "Aktuelle Zeit: " STRING_MKDIR_HELP, "Erzeugt ein Verzeichnis.\n\n\ MKDIR [Laufwerk:]Pfad\nMD [Laufwerk:]Pfad" +STRING_MKLINK_HELP, "Creates a filesystem link object.\n\n\ +MKLINK [/D | /H | /J] linkname target\n\n\ + /D Indicates that the symbolic link target is a directory.\n\ + /H Create a hard link.\n\ + /J Create a directory junction.\n\n\ +If neither /H or /J is specified, a symbolic link is created." + STRING_MEMMORY_HELP1, "Zeigt die Gre des Systemspeicher an.\n\nMEMORY" STRING_MEMMORY_HELP2, "\n %12s%% Speicher geladen.\n\n\ @@ -576,6 +583,7 @@ IF Verarbeitet Ausdr LABEL Erstellt, ndert oder lscht die Bezeichnung eines Volumes.\n\ MD Erstellt ein Verzeichnis.\n\ MKDIR Erstellt ein Verzeichnis.\n\ +MKLINK Creates a filesystem link object.\n\ MOVE Verschiebt eine oder mehrere Dateien von einem Verzeichnis in\n\ ein anderes.\n\ PATH Legt den Suchpfad fr ausfhrbare Dateien fest oder zeigt diesen an.\n\ @@ -680,6 +688,9 @@ STRING_FOR_ERROR, "ung STRING_SCREEN_COL, "ungltige Spalten-Angabe" STRING_SCREEN_ROW, "ungltige Zeilen-Angabe" STRING_TIMER_TIME "Timer %d ist %s: " +STRING_MKLINK_CREATED_SYMBOLIC, "Symbolic link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_HARD, "Hard link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_JUNCTION, "Junction created for %s <<===>> %s\n" STRING_INVALID_OPERAND, "Ungltiger Operand." STRING_EXPECTED_CLOSE_PAREN, "Erwartet ')'." STRING_EXPECTED_NUMBER_OR_VARIABLE,"Erwartet Nummer oder Variablennamen." diff --git a/reactos/base/shell/cmd/lang/el-GR.rc b/reactos/base/shell/cmd/lang/el-GR.rc index c1481013b7e..fe903084f9c 100644 --- a/reactos/base/shell/cmd/lang/el-GR.rc +++ b/reactos/base/shell/cmd/lang/el-GR.rc @@ -301,6 +301,13 @@ STRING_LOCALE_HELP1, "Current time is" STRING_MKDIR_HELP, "Creates a directory.\n\n\ MKDIR [drive:]path\nMD [drive:]path" +STRING_MKLINK_HELP, "Creates a filesystem link object.\n\n\ +MKLINK [/D | /H | /J] linkname target\n\n\ + /D Indicates that the symbolic link target is a directory.\n\ + /H Create a hard link.\n\ + /J Create a directory junction.\n\n\ +If neither /H or /J is specified, a symbolic link is created." + STRING_MEMMORY_HELP1, "Displays the amount of system memory.\n\nMEMORY" STRING_MEMMORY_HELP2, "\n %12s%% memory load.\n\n\ @@ -583,6 +590,7 @@ IF LABEL , .\n\ MD .\n\ MKDIR .\n\ +MKLINK Creates a filesystem link object.\n\ MOVE .\n\ PATH .\n\ PAUSE .\n\ @@ -697,6 +705,9 @@ STRING_FOR_ERROR, "bad variable specification." STRING_SCREEN_COL, "invalid value for col" STRING_SCREEN_ROW, "invalid value for row" STRING_TIMER_TIME "Timer %d is %s: " +STRING_MKLINK_CREATED_SYMBOLIC, "Symbolic link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_HARD, "Hard link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_JUNCTION, "Junction created for %s <<===>> %s\n" STRING_INVALID_OPERAND, "Invalid operand." STRING_EXPECTED_CLOSE_PAREN, " ')'." diff --git a/reactos/base/shell/cmd/lang/en-US.rc b/reactos/base/shell/cmd/lang/en-US.rc index e366cc0fba0..e79652c22fb 100644 --- a/reactos/base/shell/cmd/lang/en-US.rc +++ b/reactos/base/shell/cmd/lang/en-US.rc @@ -302,6 +302,13 @@ STRING_LOCALE_HELP1, "Current time is" STRING_MKDIR_HELP, "Creates a directory.\n\n\ MKDIR [drive:]path\nMD [drive:]path" +STRING_MKLINK_HELP, "Creates a filesystem link object.\n\n\ +MKLINK [/D | /H | /J] linkname target\n\n\ + /D Indicates that symbolic link target is a directory.\n\ + /H Create a hard link.\n\ + /J Create a directory junction.\n\n\ +If neither /H or /J is specified, a symbolic link is created." + STRING_MEMMORY_HELP1, "Displays the amount of system memory.\n\nMEMORY" STRING_MEMMORY_HELP2, "\n %12s%% memory load.\n\n\ @@ -584,6 +591,7 @@ IF Performs conditional processing in batch programs.\n\ LABEL Creates, changes, or deletes the volume label of a disk.\n\ MD Creates a directory.\n\ MKDIR Creates a directory.\n\ +MKLINK Creates a filesystem link object.\n\ MOVE Moves one or more files from one directory to another\n\ directory.\n\ PATH Displays or sets a search path for executable files.\n\ @@ -701,6 +709,9 @@ STRING_FOR_ERROR, "bad variable specification." STRING_SCREEN_COL, "invalid value for col" STRING_SCREEN_ROW, "invalid value for row" STRING_TIMER_TIME "Timer %d is %s: " +STRING_MKLINK_CREATED_SYMBOLIC, "Symbolic link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_HARD, "Hard link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_JUNCTION, "Junction created for %s <<===>> %s\n" STRING_INVALID_OPERAND, "Invalid operand." STRING_EXPECTED_CLOSE_PAREN, "Expected ')'." diff --git a/reactos/base/shell/cmd/lang/es-ES.rc b/reactos/base/shell/cmd/lang/es-ES.rc index cec5cab9765..13c4ae35c11 100644 --- a/reactos/base/shell/cmd/lang/es-ES.rc +++ b/reactos/base/shell/cmd/lang/es-ES.rc @@ -300,6 +300,13 @@ STRING_LOCALE_HELP1, "La hora actual es" STRING_MKDIR_HELP, "Crea un directorio.\n\n\ MKDIR [unidad:]ruta\nMD [unidad:]ruta" +STRING_MKLINK_HELP, "Creates a filesystem link object.\n\n\ +MKLINK [/D | /H | /J] linkname target\n\n\ + /D Indicates that the symbolic link target is a directory.\n\ + /H Create a hard link.\n\ + /J Create a directory junction.\n\n\ +If neither /H or /J is specified, a symbolic link is created." + STRING_MEMMORY_HELP1, "Muestra la cantidad de memoria del sistema.\n\nMEMORY" STRING_MEMMORY_HELP2, "\n %12s%% carga de memoria.\n\n\ @@ -543,6 +550,7 @@ IF Realiza un proceso condicional en un archivo por lotes.\n\ LABEL Crea, cambia, o borra la etiqueta de volumen de un disco.\n\ MD Crea un directorio.\n\ MKDIR Crea un directorio.\n\ +MKLINK Creates a filesystem link object.\n\ MOVE Mueve uno o ms archivos de un directorio a otro.\n\ PATH Muestra o configura las rutas de bsqueda para archivos ejecutables.\n\ PAUSE Suspende el procesamiento de un archivo por lotes y muestra un mensaje.\n\ @@ -649,6 +657,9 @@ STRING_FOR_ERROR, "Especici STRING_SCREEN_COL, "Valor invlido de columna" STRING_SCREEN_ROW, "Valor invlido de fila" STRING_TIMER_TIME "El temporizador %d es %s: " +STRING_MKLINK_CREATED_SYMBOLIC, "Symbolic link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_HARD, "Hard link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_JUNCTION, "Junction created for %s <<===>> %s\n" STRING_INVALID_OPERAND, "Operador errneo.\n" STRING_EXPECTED_CLOSE_PAREN, "Se esperaba ')'.\n" diff --git a/reactos/base/shell/cmd/lang/fr-FR.rc b/reactos/base/shell/cmd/lang/fr-FR.rc index 3251feae1db..308e0286b16 100644 --- a/reactos/base/shell/cmd/lang/fr-FR.rc +++ b/reactos/base/shell/cmd/lang/fr-FR.rc @@ -313,6 +313,13 @@ STRING_LOCALE_HELP1, "L'heure actuelle est " STRING_MKDIR_HELP, "Cre un rpertoire.\n\n\ MKDIR [lecteur:]chemin\nMD [lecteur:]chemin" +STRING_MKLINK_HELP, "Creates a filesystem link object.\n\n\ +MKLINK [/D | /H | /J] linkname target\n\n\ + /D Indicates that the symbolic link target is a directory.\n\ + /H Create a hard link.\n\ + /J Create a directory junction.\n\n\ +If neither /H or /J is specified, a symbolic link is created." + STRING_MEMMORY_HELP1, "Affiche la quantit de mmoire systme.\n\nMEMORY" STRING_MEMMORY_HELP2, "\n %12s%% de charge mmoire.\n\n\ @@ -597,6 +604,7 @@ IF Ex LABEL Cr, change, ou supprime le nom de volume d'un disque.\n\ MD Cr un rpertoire.\n\ MKDIR Cr un rpertoire.\n\ +MKLINK Creates a filesystem link object.\n\ MOVE Dplace un ou plusieurs fichiers d'un rpertoire vers un autre\n\ rpertoire.\n\ PATH Affiche ou dfini un chemin de recherche pour les fichiers excutables.\n\ @@ -715,6 +723,9 @@ STRING_FOR_ERROR, "mauvaise variable sp STRING_SCREEN_COL, "valeur invalide pour col" STRING_SCREEN_ROW, "valeur invalide pour lig" STRING_TIMER_TIME "Le timer n%d est %s : " +STRING_MKLINK_CREATED_SYMBOLIC, "Symbolic link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_HARD, "Hard link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_JUNCTION, "Junction created for %s <<===>> %s\n" STRING_INVALID_OPERAND, "Oprande invalide." STRING_EXPECTED_CLOSE_PAREN, "Attendu ')'." diff --git a/reactos/base/shell/cmd/lang/hu-HU.rc b/reactos/base/shell/cmd/lang/hu-HU.rc index f98707eb517..0efe23b5b34 100644 --- a/reactos/base/shell/cmd/lang/hu-HU.rc +++ b/reactos/base/shell/cmd/lang/hu-HU.rc @@ -289,6 +289,13 @@ STRING_LOCALE_HELP1, "Az aktu STRING_MKDIR_HELP, "Ltrehoz egy j mappt.\n\n\ MKDIR [meghajt:]path\nMD [meghajt:]path" +STRING_MKLINK_HELP, "Creates a filesystem link object.\n\n\ +MKLINK [/D | /H | /J] linkname target\n\n\ + /D Indicates that the symbolic link target is a directory.\n\ + /H Create a hard link.\n\ + /J Create a directory junction.\n\n\ +If neither /H or /J is specified, a symbolic link is created." + STRING_MEMMORY_HELP1, "Megjelenti a memria statisztikt.\n\nMEMORY" STRING_MEMMORY_HELP2, "\n A memria %12s%%-a foglalt.\n\n\ @@ -526,6 +533,7 @@ IF Felt LABEL Belltja egy ktet cmkjt.\n\ MD Ltrehoz egy j mappt.\n\ MKDIR Ltrehoz egy j mappt.\n\ +MKLINK Creates a filesystem link object.\n\ MOVE thelyez egy vagy tbb llomnyt az egyik mappbl a msikba.\n\ PATH Megjelenti vagy belltja a keressi tvonalakat.\n\ PAUSE Felfggeszti a futst, s vr a felhasznlra.\n\ @@ -629,4 +637,7 @@ STRING_FOR_ERROR, "Hib STRING_SCREEN_COL, "rvnytelen rtk oszlopnak" STRING_SCREEN_ROW, "rvnytelen rtk sornak" STRING_TIMER_TIME "Idzt %d rtke %s: " +STRING_MKLINK_CREATED_SYMBOLIC, "Symbolic link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_HARD, "Hard link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_JUNCTION, "Junction created for %s <<===>> %s\n" END diff --git a/reactos/base/shell/cmd/lang/id-ID.rc b/reactos/base/shell/cmd/lang/id-ID.rc index ea589058165..3dccfe31a8c 100644 --- a/reactos/base/shell/cmd/lang/id-ID.rc +++ b/reactos/base/shell/cmd/lang/id-ID.rc @@ -302,6 +302,13 @@ STRING_LOCALE_HELP1, "Waktu saat ini" STRING_MKDIR_HELP, "Membuat direktori.\n\n\ MKDIR [drive:]path\nMD [drive:]path" +STRING_MKLINK_HELP, "Creates a filesystem link object.\n\n\ +MKLINK [/D | /H | /J] linkname target\n\n\ + /D Indicates that the symbolic link target is a directory.\n\ + /H Create a hard link.\n\ + /J Create a directory junction.\n\n\ +If neither /H or /J is specified, a symbolic link is created." + STRING_MEMMORY_HELP1, "Menampilkan jumlah memori sistem.\n\nMEMORY" STRING_MEMMORY_HELP2, "\n %12s%% beban memori.\n\n\ @@ -542,6 +549,7 @@ IF Melakukan pemrosesan kondisional dalam program batch.\n\ LABEL Membuat, mengubah, atau menghapus label volume disk.\n\ MD Membuat sebuah direktori.\n\ MKDIR Membuat sebuah direktori.\n\ +MKLINK Creates a filesystem link object.\n\ MOVE Memindahkan satu atau lebih file dari satu direktori ke yang lainnya\n\ directory.\n\ PATH Menampilkan atau menyetel path pencarian untuk file executable.\n\ @@ -651,6 +659,9 @@ STRING_FOR_ERROR, "spesifikasi variabel tidak baik." STRING_SCREEN_COL, "Nilai untuk kolom tidak benar" STRING_SCREEN_ROW, "Nilai untuk baris tidak benar" STRING_TIMER_TIME "Timer %d adalah %s: " +STRING_MKLINK_CREATED_SYMBOLIC, "Symbolic link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_HARD, "Hard link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_JUNCTION, "Junction created for %s <<===>> %s\n" STRING_INVALID_OPERAND, "Operand tidak benar." STRING_EXPECTED_CLOSE_PAREN, "Diharapkan ')'." diff --git a/reactos/base/shell/cmd/lang/it-IT.rc b/reactos/base/shell/cmd/lang/it-IT.rc index cbba0fa50d7..54a15667ace 100644 --- a/reactos/base/shell/cmd/lang/it-IT.rc +++ b/reactos/base/shell/cmd/lang/it-IT.rc @@ -301,6 +301,13 @@ STRING_LOCALE_HELP1, "L'ora attuale STRING_MKDIR_HELP, "Crea una cartella.\n\n\ MKDIR [disco:]percorso\nMD [disco:]percorso" +STRING_MKLINK_HELP, "Creates a filesystem link object.\n\n\ +MKLINK [/D | /H | /J] linkname target\n\n\ + /D Indicates that the symbolic link target is a directory.\n\ + /H Create a hard link.\n\ + /J Create a directory junction.\n\n\ +If neither /H or /J is specified, a symbolic link is created." + STRING_MEMMORY_HELP1, "Visualizza la quantit della memoria di sistema.\n\n\ MEMORY" @@ -590,6 +597,7 @@ IF Esegue elaborazioni condizionali in un batch.\n\ LABEL Crea, modifica, o cancella l'etichetta di un disco.\n\ MD Crea una cartella.\n\ MKDIR Crea una cartella.\n\ +MKLINK Creates a filesystem link object.\n\ MOVE Muove uno o pi file da una cartella a un'altra\n\ PATH Visualizza o imposta i percorsi di ricerca per gli eseguibili.\n\ PAUSE Ferma l'esecuzione di un batch e visualizza un messaggio.\n\ @@ -705,6 +713,9 @@ STRING_FOR_ERROR, "variabile non valida." STRING_SCREEN_COL, "valore non valido per colonna" STRING_SCREEN_ROW, "valore non valido per riga" STRING_TIMER_TIME "Timer %d %s: " +STRING_MKLINK_CREATED_SYMBOLIC, "Symbolic link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_HARD, "Hard link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_JUNCTION, "Junction created for %s <<===>> %s\n" STRING_INVALID_OPERAND, "Operando non valido." STRING_EXPECTED_CLOSE_PAREN, "Attesa una ')'." diff --git a/reactos/base/shell/cmd/lang/ja-JP.rc b/reactos/base/shell/cmd/lang/ja-JP.rc index f1d9d4db620..6a235b0b861 100644 --- a/reactos/base/shell/cmd/lang/ja-JP.rc +++ b/reactos/base/shell/cmd/lang/ja-JP.rc @@ -310,6 +310,13 @@ STRING_MKDIR_HELP, " MKDIR [hCu:]pX\n\ MD [hCu:]pX" +STRING_MKLINK_HELP, "Creates a filesystem link object.\n\n\ +MKLINK [/D | /H | /J] linkname target\n\n\ + /D Indicates that the symbolic link target is a directory.\n\ + /H Create a hard link.\n\ + /J Create a directory junction.\n\n\ +If neither /H or /J is specified, a symbolic link is created." + STRING_MEMMORY_HELP1, "VXe ̗ʂ\\܂B\n\nMEMORY" STRING_MEMMORY_HELP2, "\n %12s%% ̃gpĂ܂B\n\n\ @@ -551,6 +558,7 @@ IF LABEL fBXÑ{[ x\\܂͕ύX܂B\n\ MD fBNg쐬܂B\n\ MKDIR fBNg쐬܂B\n\ +MKLINK Creates a filesystem link object.\n\ MOVE t@Cړуt@CƃfBNgύX܂B\n\ PATH s”\\t@ČpX\\܂͐ݒ肵܂B\n\ PAUSE ob` vȌꎞ~AbZ[W\\܂B\n\ @@ -658,6 +666,9 @@ STRING_FOR_ERROR, " STRING_SCREEN_COL, "s̒lłB" STRING_SCREEN_ROW, "̒lłB" STRING_TIMER_TIME "^C}[ %d %s łB: " +STRING_MKLINK_CREATED_SYMBOLIC, "Symbolic link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_HARD, "Hard link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_JUNCTION, "Junction created for %s <<===>> %s\n" STRING_INVALID_OPERAND, "ȃIyhłB" STRING_EXPECTED_CLOSE_PAREN, "Expected ')'" diff --git a/reactos/base/shell/cmd/lang/no-NO.rc b/reactos/base/shell/cmd/lang/no-NO.rc index 39c663b8802..cc87faaf5dc 100644 --- a/reactos/base/shell/cmd/lang/no-NO.rc +++ b/reactos/base/shell/cmd/lang/no-NO.rc @@ -294,6 +294,13 @@ STRING_LOCALE_HELP1, "gjeldende tid er" STRING_MKDIR_HELP, "Oppretter en mappe.\n\n\ MKDIR [stasjon:]mappe\nMD [stasjon:]mappe" +STRING_MKLINK_HELP, "Creates a filesystem link object.\n\n\ +MKLINK [/D | /H | /J] linkname target\n\n\ + /D Indicates that the symbolic link target is a directory.\n\ + /H Create a hard link.\n\ + /J Create a directory junction.\n\n\ +If neither /H or /J is specified, a symbolic link is created." + STRING_MEMMORY_HELP1, "Vis mengde av system minne.\n\nMEMORY" STRING_MEMMORY_HELP2, "\n %12s%% benyttet minne.\n\n\ @@ -534,6 +541,7 @@ IF Utf LABEL Oppretter, endrer, eller sletter volumnavnet p en disk.\n\ MD Oppretter en mappe.\n\ MKDIR Oppretter en mappe.\n\ +MKLINK Creates a filesystem link object.\n\ MOVE Flytter en eller flere filer fra en mappe til en annen.\n\ PATH Vis eller sett en skesti for kjrbare filer.\n\ PAUSE Avbryter behandling av en satsvis fil, og viser en melding.\n\ @@ -643,6 +651,9 @@ STRING_FOR_ERROR, "ugyldig variabel spesifikasjon." STRING_SCREEN_COL, "ugyldig verdi for kolonne" STRING_SCREEN_ROW, "ugyldig verdi for rad" STRING_TIMER_TIME "Stoppeklokke %d er %s: " +STRING_MKLINK_CREATED_SYMBOLIC, "Symbolic link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_HARD, "Hard link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_JUNCTION, "Junction created for %s <<===>> %s\n" STRING_INVALID_OPERAND, "Ugyldig operand." STRING_EXPECTED_CLOSE_PAREN, "Forventet ')'." diff --git a/reactos/base/shell/cmd/lang/pl-PL.rc b/reactos/base/shell/cmd/lang/pl-PL.rc index 3cfc885d5a7..974c8078626 100644 --- a/reactos/base/shell/cmd/lang/pl-PL.rc +++ b/reactos/base/shell/cmd/lang/pl-PL.rc @@ -300,6 +300,13 @@ STRING_LOCALE_HELP1, "Czas bie STRING_MKDIR_HELP, "Tworzy katalog.\n\n\ MKDIR [napd:]cieka\nMD [napd:]cieka" +STRING_MKLINK_HELP, "Creates a filesystem link object.\n\n\ +MKLINK [/D | /H | /J] linkname target\n\n\ + /D Indicates that the symbolic link target is a directory.\n\ + /H Create a hard link.\n\ + /J Create a directory junction.\n\n\ +If neither /H or /J is specified, a symbolic link is created." + STRING_MEMMORY_HELP1, "Wywietla ilo pamici systemowej.\n\nMEMORY" STRING_MEMMORY_HELP2, "\n %12s%% pamici zajtej.\n\n\ @@ -541,6 +548,7 @@ IF Przetwarzanie warunkowe w programach wsadowych.\n\ LABEL Tworzy, zmienia lub kasuje etykiet woluminu w danym napdzie.\n\ MD Tworzy katalog.\n\ MKDIR Tworzy katalog.\n\ +MKLINK Creates a filesystem link object.\n\ MOVE Przenosi jeden lub wicej plikw z jednego katalogu do drugiego.\n\ PATH Wywietla lub ustawia cieki dostpu dla programw.\n\ PAUSE Zawiesza przetwarzanie programu wsadowego i wywietla komunikat.\n\ @@ -649,6 +657,9 @@ STRING_FOR_ERROR, "z STRING_SCREEN_COL, "nieprawidowy numer kolumny" STRING_SCREEN_ROW, "nieprawidowy numer rzdu" STRING_TIMER_TIME "Stoper %d czas - %s: " +STRING_MKLINK_CREATED_SYMBOLIC, "Symbolic link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_HARD, "Hard link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_JUNCTION, "Junction created for %s <<===>> %s\n" STRING_INVALID_OPERAND, "Nieprawidowy argument operatora." STRING_EXPECTED_CLOSE_PAREN, "Oczekiwano ')'." diff --git a/reactos/base/shell/cmd/lang/ru-RU.rc b/reactos/base/shell/cmd/lang/ru-RU.rc index 230f7588797..c9f36c25806 100644 --- a/reactos/base/shell/cmd/lang/ru-RU.rc +++ b/reactos/base/shell/cmd/lang/ru-RU.rc @@ -307,6 +307,13 @@ STRING_LOCALE_HELP1, " STRING_MKDIR_HELP, " .\n\n\ MKDIR [:]\nMD [:]" +STRING_MKLINK_HELP, "Creates a filesystem link object.\n\n\ +MKLINK [/D | /H | /J] linkname target\n\n\ + /D Indicates that the symbolic link target is a directory.\n\ + /H Create a hard link.\n\ + /J Create a directory junction.\n\n\ +If neither /H or /J is specified, a symbolic link is created." + STRING_MEMMORY_HELP1, " .\n\nMEMORY" STRING_MEMMORY_HELP2, "\n %12s%% memory load.\n\n\ @@ -548,6 +555,7 @@ IF LABEL , .\n\ MD .\n\ MKDIR .\n\ +MKLINK Creates a filesystem link object.\n\ MOVE \n\ PATH .\n\ PAUSE .\n\ @@ -656,6 +664,9 @@ STRING_FOR_ERROR, " STRING_SCREEN_COL, " " STRING_SCREEN_ROW, " " STRING_TIMER_TIME "Timer %d is %s: " +STRING_MKLINK_CREATED_SYMBOLIC, "Symbolic link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_HARD, "Hard link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_JUNCTION, "Junction created for %s <<===>> %s\n" STRING_INVALID_OPERAND, " ." STRING_EXPECTED_CLOSE_PAREN, " ')'." diff --git a/reactos/base/shell/cmd/lang/uk-UA.rc b/reactos/base/shell/cmd/lang/uk-UA.rc index c8446eb7a7e..bf5fd768e7b 100644 --- a/reactos/base/shell/cmd/lang/uk-UA.rc +++ b/reactos/base/shell/cmd/lang/uk-UA.rc @@ -306,6 +306,13 @@ STRING_LOCALE_HELP1, "Current time is" STRING_MKDIR_HELP, "Creates a directory.\n\n\ MKDIR [drive:]path\nMD [drive:]path" +STRING_MKLINK_HELP, "Creates a filesystem link object.\n\n\ +MKLINK [/D | /H | /J] linkname target\n\n\ + /D Indicates that the symbolic link target is a directory.\n\ + /H Create a hard link.\n\ + /J Create a directory junction.\n\n\ +If neither /H or /J is specified, a symbolic link is created." + STRING_MEMMORY_HELP1, "Displays the amount of system memory.\n\nMEMORY" STRING_MEMMORY_HELP2, "\n %12s%% memory load.\n\n\ @@ -587,6 +594,7 @@ IF LABEL , , .\n\ MD .\n\ MKDIR .\n\ +MKLINK Creates a filesystem link object.\n\ MOVE \n\ .\n\ PATH ³ .\n\ @@ -705,6 +713,9 @@ STRING_FOR_ERROR, "bad variable specification." STRING_SCREEN_COL, " col" STRING_SCREEN_ROW, " row" STRING_TIMER_TIME " %d - %s: " +STRING_MKLINK_CREATED_SYMBOLIC, "Symbolic link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_HARD, "Hard link created for %s <<===>> %s\n" +STRING_MKLINK_CREATED_JUNCTION, "Junction created for %s <<===>> %s\n" STRING_INVALID_OPERAND, " ." STRING_EXPECTED_CLOSE_PAREN, " ')'." diff --git a/reactos/base/shell/cmd/mklink.c b/reactos/base/shell/cmd/mklink.c new file mode 100644 index 00000000000..ecd0a81b72e --- /dev/null +++ b/reactos/base/shell/cmd/mklink.c @@ -0,0 +1,219 @@ +/* + * MKLINK.C - mklink internal command. + */ + +#include + +#ifdef INCLUDE_CMD_MKLINK + +/* There is no API for creating junctions, so we must do it the hard way */ +static BOOL CreateJunction(LPCTSTR LinkName, LPCTSTR TargetName) +{ + /* Structure for reparse point daya when ReparseTag is one of + * the tags defined by Microsoft. Copied from MinGW winnt.h */ + typedef struct _REPARSE_DATA_BUFFER { + DWORD ReparseTag; + WORD ReparseDataLength; + WORD Reserved; + _ANONYMOUS_UNION union { + struct { + WORD SubstituteNameOffset; + WORD SubstituteNameLength; + WORD PrintNameOffset; + WORD PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[1]; + } SymbolicLinkReparseBuffer; + struct { + WORD SubstituteNameOffset; + WORD SubstituteNameLength; + WORD PrintNameOffset; + WORD PrintNameLength; + WCHAR PathBuffer[1]; + } MountPointReparseBuffer; + struct { + BYTE DataBuffer[1]; + } GenericReparseBuffer; + } DUMMYUNIONNAME; + } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; + + HMODULE hNTDLL = GetModuleHandle(_T("NTDLL")); + BOOLEAN (WINAPI *RtlDosPathNameToNtPathName_U)(PCWSTR, PUNICODE_STRING, PCWSTR *, CURDIR *) + = (BOOLEAN (WINAPI *)())GetProcAddress(hNTDLL, "RtlDosPathNameToNtPathName_U"); + VOID (WINAPI *RtlFreeUnicodeString)(PUNICODE_STRING) + = (VOID (WINAPI *)())GetProcAddress(hNTDLL, "RtlFreeUnicodeString"); + + TCHAR TargetFullPath[MAX_PATH]; +#ifdef UNICODE +#define TargetFullPathW TargetFullPath +#else + WCHAR TargetFullPathW[MAX_PATH]; +#endif + UNICODE_STRING TargetNTPath; + HANDLE hJunction; + + /* The data for this kind of reparse point has two strings: + * The first ("SubstituteName") is the full target path in NT format, + * the second ("PrintName") is the full target path in Win32 format. + * Both of these must be wide-character strings. */ + if (!RtlDosPathNameToNtPathName_U || + !RtlFreeUnicodeString || + !GetFullPathName(TargetName, MAX_PATH, TargetFullPath, NULL) || +#ifndef UNICODE + !MultiByteToWideChar(CP_ACP, 0, TargetFullPath, -1, TargetFullPathW, -1) || +#endif + !RtlDosPathNameToNtPathName_U(TargetFullPathW, &TargetNTPath, NULL, NULL)) + { + return FALSE; + } + + /* We have both the names we need, so time to create the junction. + * Start with an empty directory */ + if (!CreateDirectory(LinkName, NULL)) + { + RtlFreeUnicodeString(&TargetNTPath); + return FALSE; + } + + /* Open the directory we just created */ + hJunction = CreateFile(LinkName, GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (hJunction != INVALID_HANDLE_VALUE) + { + /* Allocate a buffer large enough to hold both strings, including trailing NULs */ + DWORD TargetLen = wcslen(TargetFullPathW) * sizeof(WCHAR); + DWORD DataSize = FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) + + TargetNTPath.Length + sizeof(WCHAR) + + TargetLen + sizeof(WCHAR); + PREPARSE_DATA_BUFFER Data = _alloca(DataSize); + + /* Fill it out and use it to turn the directory into a reparse point */ + Data->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; + Data->ReparseDataLength = DataSize - FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer); + Data->Reserved = 0; + Data->MountPointReparseBuffer.SubstituteNameOffset = 0; + Data->MountPointReparseBuffer.SubstituteNameLength = TargetNTPath.Length; + wcscpy(Data->MountPointReparseBuffer.PathBuffer, + TargetNTPath.Buffer); + Data->MountPointReparseBuffer.PrintNameOffset = TargetNTPath.Length + sizeof(WCHAR); + Data->MountPointReparseBuffer.PrintNameLength = TargetLen; + wcscpy((WCHAR *)((BYTE *)Data->MountPointReparseBuffer.PathBuffer + + Data->MountPointReparseBuffer.PrintNameOffset), + TargetFullPathW); + if (DeviceIoControl(hJunction, FSCTL_SET_REPARSE_POINT, + Data, DataSize, NULL, 0, &DataSize, NULL)) + { + /* Success */ + CloseHandle(hJunction); + RtlFreeUnicodeString(&TargetNTPath); + return TRUE; + } + CloseHandle(hJunction); + } + RemoveDirectory(LinkName); + RtlFreeUnicodeString(&TargetNTPath); + return FALSE; +} + +INT +cmd_mklink(LPTSTR param) +{ + HMODULE hKernel32 = GetModuleHandle(_T("KERNEL32")); + DWORD Flags = 0; + enum { SYMBOLIC, HARD, JUNCTION } LinkType = SYMBOLIC; + INT NumFiles = 0; + LPTSTR Name[2]; + INT argc, i; + LPTSTR *arg; + + if (!_tcsncmp(param, _T("/?"), 2)) + { + ConOutResPuts(STRING_MKLINK_HELP); + return 0; + } + + arg = split(param, &argc, FALSE); + for (i = 0; i < argc; i++) + { + if (arg[i][0] == _T('/')) + { + if (!_tcsicmp(arg[i], _T("/D"))) + Flags |= 1; /* SYMBOLIC_LINK_FLAG_DIRECTORY */ + else if (!_tcsicmp(arg[i], _T("/H"))) + LinkType = HARD; + else if (!_tcsicmp(arg[i], _T("/J"))) + LinkType = JUNCTION; + else + { + error_invalid_switch(arg[i][1]); + freep(arg); + return 1; + } + } + else + { + if (NumFiles == 2) + { + error_too_many_parameters(arg[i]); + freep(arg); + return 1; + } + Name[NumFiles++] = arg[i]; + } + } + freep(arg); + + if (NumFiles != 2) + { + error_req_param_missing(); + return 1; + } + + nErrorLevel = 0; + + if (LinkType == SYMBOLIC) + { + /* CreateSymbolicLink doesn't exist in old versions of Windows, + * so load dynamically */ + BOOL (WINAPI *CreateSymbolicLink)(LPCTSTR, LPCTSTR, DWORD) +#ifdef UNICODE + = (BOOL (WINAPI *)())GetProcAddress(hKernel32, "CreateSymbolicLinkW"); +#else + = (BOOL (WINAPI *)())GetProcAddress(hKernel32, "CreateSymbolicLinkA"); +#endif + if (CreateSymbolicLink && CreateSymbolicLink(Name[0], Name[1], Flags)) + { + ConOutResPrintf(STRING_MKLINK_CREATED_SYMBOLIC, Name[0], Name[1]); + return 0; + } + } + else if (LinkType == HARD) + { + /* CreateHardLink doesn't exist in old versions of Windows, + * so load dynamically */ + BOOL (WINAPI *CreateHardLink)(LPCTSTR, LPCTSTR, LPSECURITY_ATTRIBUTES) +#ifdef UNICODE + = (BOOL (WINAPI *)())GetProcAddress(hKernel32, "CreateHardLinkW"); +#else + = (BOOL (WINAPI *)())GetProcAddress(hKernel32, "CreateHardLinkA"); +#endif + if (CreateHardLink && CreateHardLink(Name[0], Name[1], NULL)) + { + ConOutResPrintf(STRING_MKLINK_CREATED_HARD, Name[0], Name[1]); + return 0; + } + } + else + { + if (CreateJunction(Name[0], Name[1])) + { + ConOutResPrintf(STRING_MKLINK_CREATED_JUNCTION, Name[0], Name[1]); + return 0; + } + } + + ErrorMessage(GetLastError(), _T("MKLINK")); + return 1; +} + +#endif /* INCLUDE_CMD_MKLINK */ diff --git a/reactos/base/shell/cmd/resource.h b/reactos/base/shell/cmd/resource.h index 39ecd173831..52cace43a93 100644 --- a/reactos/base/shell/cmd/resource.h +++ b/reactos/base/shell/cmd/resource.h @@ -89,6 +89,7 @@ #define STRING_CMD_HELP7 614 #define STRING_CMD_HELP8 615 #define STRING_ASSOC_HELP 616 +#define STRING_MKLINK_HELP 617 #define STRING_CMD_SHELLINFO 624 @@ -242,6 +243,9 @@ #define STRING_REPLACE_HELP10 736 #define STRING_REPLACE_HELP11 737 +#define STRING_MKLINK_CREATED_SYMBOLIC 738 +#define STRING_MKLINK_CREATED_HARD 739 +#define STRING_MKLINK_CREATED_JUNCTION 740 /* These strings are language independent (cmd.rc) */ #define STRING_FREEDOS_DEV 800