diff --git a/reactos/base/applications/applications.rbuild b/reactos/base/applications/applications.rbuild
index ca1fe852e3c..aafcf9e527e 100644
--- a/reactos/base/applications/applications.rbuild
+++ b/reactos/base/applications/applications.rbuild
@@ -25,6 +25,9 @@
+
+
+
diff --git a/reactos/base/applications/logoff/lang/en-US.rc b/reactos/base/applications/logoff/lang/en-US.rc
new file mode 100644
index 00000000000..64a3e2a4fc7
--- /dev/null
+++ b/reactos/base/applications/logoff/lang/en-US.rc
@@ -0,0 +1,15 @@
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+STRINGTABLE DISCARDABLE
+{
+
+IDS_USAGE, "Terminates a session.\n\n\
+ /v\t\tDisplays information about the actions performed.\n\
+ /?\t\tShows this information.\n\n"
+
+IDS_LOGOFF_REMOTE, "Terminating session on remote machine."
+IDS_LOGOFF_LOCAL, "Terminating the current session on this machine."
+
+IDS_ILLEGAL_PARAM, "Invalid parameter(s)\n"
+}
+/* EOF */
diff --git a/reactos/base/applications/logoff/lang/nb-NO.rc b/reactos/base/applications/logoff/lang/nb-NO.rc
new file mode 100644
index 00000000000..b4f8a8826e1
--- /dev/null
+++ b/reactos/base/applications/logoff/lang/nb-NO.rc
@@ -0,0 +1,16 @@
+LANGUAGE LANG_NORWEGIAN, SUBLANG_NEUTRAL
+
+STRINGTABLE DISCARDABLE
+{
+
+IDS_USAGE, "Avslutter en sesjon.\n\n\
+ /v\t\tViser informasjon om handlingen som utføres.\n\
+ /?\t\tViser denne informasjonen.\n\n"
+
+IDS_LOGOFF_REMOTE, "Logger av økt på en annen maskin"
+IDS_LOGOFF_LOCAL, "Logger av økten på denne maskinen."
+
+IDS_ILLEGAL_PARAM, "En eller flere ugyldige parametre.\n"
+}
+
+/* EOF */
diff --git a/reactos/base/applications/logoff/logoff.c b/reactos/base/applications/logoff/logoff.c
new file mode 100644
index 00000000000..d333fc97815
--- /dev/null
+++ b/reactos/base/applications/logoff/logoff.c
@@ -0,0 +1,146 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS logoff utility
+ * FILE: base\applications\logoff\logoff.c
+ * PURPOSE: Logoff current session, or another session, potentially on another machine
+ * AUTHOR: 30.07.2007 - Frode Lillerud
+ */
+
+/* Note
+ * This application is a lightweight version of shutdown.exe. It is intended to be function-compatible
+ * with Windows' system32\logoff.exe commandline application.
+ */
+
+#define NDEBUG
+#include "precomp.h"
+
+//Commandline argument switches
+LPTSTR szRemoteServerName = NULL;
+BOOL bVerbose;
+
+//----------------------------------------------------------------------
+//
+//Retrieve resource string and output the Usage to the console
+//
+//----------------------------------------------------------------------
+static void PrintUsage() {
+ LPTSTR lpUsage = NULL;
+
+ if (AllocAndLoadString(&lpUsage, GetModuleHandle(NULL), IDS_USAGE)) {
+ _putts(lpUsage);
+ }
+
+}
+
+//----------------------------------------------------------------------
+//
+// Writes the last error as both text and error code to the console.
+//
+//----------------------------------------------------------------------
+void DisplayLastError()
+{
+ int errorCode = GetLastError();
+ LPTSTR lpMsgBuf;
+
+ // Display the error message to the user
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ errorCode,
+ LANG_USER_DEFAULT,
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL);
+
+ _ftprintf(stderr, lpMsgBuf);
+ _ftprintf(stderr, _T("Error code: %d\n"), errorCode);
+
+ LocalFree(lpMsgBuf);
+}
+
+//----------------------------------------------------------------------
+//
+//Sets flags based on commandline arguments
+//
+//----------------------------------------------------------------------
+BOOL ParseCommandLine(int argc, TCHAR *argv[])
+{
+ int i;
+ LPTSTR lpIllegalMsg;
+
+ //FIXME: Add handling of commandline arguments to select the session number and name, and also name of remote machine
+ //Example: logoff.exe 4 /SERVER:Master should logoff session number 4 on remote machine called Master.
+
+ for (i = 1; i < argc; i++) {
+ switch(argv[i][0]){
+ case '-':
+ case '/':
+ // -v (verbose)
+ if (argv[i][1] == 'v') {
+ bVerbose = TRUE;
+ break; //continue parsing the arguments
+ }
+ // -? (usage)
+ else if(argv[i][1] == '?') {
+ return FALSE; //display the Usage
+ }
+ default:
+ //Invalid parameter detected
+ if (AllocAndLoadString(&lpIllegalMsg, GetModuleHandle(NULL), IDS_ILLEGAL_PARAM))
+ _putts(lpIllegalMsg);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+//----------------------------------------------------------------------
+//
+//Main entry for program
+//
+//----------------------------------------------------------------------
+int _tmain(int argc, TCHAR *argv[])
+{
+ LPTSTR lpLogoffRemote, lpLogoffLocal;
+
+ //
+ // Parse command line
+ //
+ if (!ParseCommandLine(argc, argv)) {
+ PrintUsage();
+ return 1;
+ }
+
+ //
+ //Should we log off session on remote server?
+ //
+ if (szRemoteServerName) {
+ if (bVerbose) {
+ if (AllocAndLoadString(&lpLogoffRemote, GetModuleHandle(NULL), IDS_LOGOFF_REMOTE))
+ _putts(lpLogoffRemote);
+ }
+
+ //FIXME: Add Remote Procedure Call to logoff user on a remote machine
+ _ftprintf(stderr, "Remote Procedure Call in logoff.exe has not been implemented");
+ }
+ //
+ //Perform logoff of current session on local machine instead
+ //
+ else {
+ if (bVerbose) {
+ //Get resource string, and print it.
+ if (AllocAndLoadString(&lpLogoffLocal, GetModuleHandle(NULL), IDS_LOGOFF_LOCAL))
+ _putts(lpLogoffLocal);
+ }
+
+ //Actual logoff
+ if (!ExitWindows(NULL, NULL)) {
+ DisplayLastError();
+ return 1;
+ }
+ }
+
+ return 0;
+}
+/* EOF */
diff --git a/reactos/base/applications/logoff/logoff.rbuild b/reactos/base/applications/logoff/logoff.rbuild
new file mode 100644
index 00000000000..4333531c3c6
--- /dev/null
+++ b/reactos/base/applications/logoff/logoff.rbuild
@@ -0,0 +1,14 @@
+
+
+
+ .
+
+ 0x0501
+ advapi32
+ user32
+ kernel32
+ misc.c
+ logoff.c
+ logoff.rc
+ precomp.h
+
diff --git a/reactos/base/applications/logoff/logoff.rc b/reactos/base/applications/logoff/logoff.rc
new file mode 100644
index 00000000000..1ff19aa5ef8
--- /dev/null
+++ b/reactos/base/applications/logoff/logoff.rc
@@ -0,0 +1,9 @@
+#include
+#include "resource.h"
+
+#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Logoff Utility\0"
+#define REACTOS_STR_INTERNAL_NAME "logoff\0"
+#define REACTOS_STR_ORIGINAL_FILENAME "logoff.exe\0"
+#include
+
+#include "rsrc.rc"
diff --git a/reactos/base/applications/logoff/misc.c b/reactos/base/applications/logoff/misc.c
new file mode 100644
index 00000000000..d7b042bc501
--- /dev/null
+++ b/reactos/base/applications/logoff/misc.c
@@ -0,0 +1,63 @@
+#include "precomp.h"
+
+static INT
+LengthOfStrResource(IN HINSTANCE hInst,
+ IN UINT uID)
+{
+ HRSRC hrSrc;
+ HGLOBAL hRes;
+ LPWSTR lpName, lpStr;
+
+ if (hInst == NULL)
+ {
+ return -1;
+ }
+
+ /* There are always blocks of 16 strings */
+ lpName = (LPWSTR)MAKEINTRESOURCE((uID >> 4) + 1);
+
+ /* Find the string table block */
+ if ((hrSrc = FindResourceW(hInst, lpName, (LPWSTR)RT_STRING)) &&
+ (hRes = LoadResource(hInst, hrSrc)) &&
+ (lpStr = (WCHAR*) LockResource(hRes)))
+ {
+ UINT x;
+
+ /* Find the string we're looking for */
+ uID &= 0xF; /* position in the block, same as % 16 */
+ for (x = 0; x < uID; x++)
+ {
+ lpStr += (*lpStr) + 1;
+ }
+
+ /* Found the string */
+ return (int)(*lpStr);
+ }
+ return -1;
+}
+
+INT
+AllocAndLoadString(OUT LPTSTR *lpTarget,
+ IN HINSTANCE hInst,
+ IN UINT uID)
+{
+ INT ln;
+
+ ln = LengthOfStrResource(hInst,
+ uID);
+ if (ln++ > 0)
+ {
+ (*lpTarget) = (LPTSTR)LocalAlloc(LMEM_FIXED,
+ ln * sizeof(TCHAR));
+ if ((*lpTarget) != NULL)
+ {
+ INT Ret;
+ if (!(Ret = LoadString(hInst, uID, *lpTarget, ln)))
+ {
+ LocalFree((HLOCAL)(*lpTarget));
+ }
+ return Ret;
+ }
+ }
+ return 0;
+}
diff --git a/reactos/base/applications/logoff/precomp.h b/reactos/base/applications/logoff/precomp.h
new file mode 100644
index 00000000000..24e122baefc
--- /dev/null
+++ b/reactos/base/applications/logoff/precomp.h
@@ -0,0 +1,16 @@
+#ifndef __SHUTDOWN_PRECOMP_H
+#define __SHUTDOWN_PRECOMP_H
+
+#include
+#include
+#include
+#include
+#include //shutdown codes
+#include "resource.h"
+
+// misc.c
+INT AllocAndLoadString(OUT LPTSTR *lpTarget,
+ IN HINSTANCE hInst,
+ IN UINT uID);
+
+#endif
diff --git a/reactos/base/applications/logoff/resource.h b/reactos/base/applications/logoff/resource.h
new file mode 100644
index 00000000000..a04334117e1
--- /dev/null
+++ b/reactos/base/applications/logoff/resource.h
@@ -0,0 +1,4 @@
+#define IDS_USAGE 1000
+#define IDS_LOGOFF_REMOTE 1001
+#define IDS_LOGOFF_LOCAL 1002
+#define IDS_ILLEGAL_PARAM 1003
diff --git a/reactos/base/applications/logoff/rsrc.rc b/reactos/base/applications/logoff/rsrc.rc
new file mode 100644
index 00000000000..2bbd29e394b
--- /dev/null
+++ b/reactos/base/applications/logoff/rsrc.rc
@@ -0,0 +1,5 @@
+#include
+#include "resource.h"
+
+#include "lang/en-US.rc"
+#include "lang/nb-NO.rc"
diff --git a/reactos/boot/bootdata/packages/reactos.dff b/reactos/boot/bootdata/packages/reactos.dff
index bae00ee8270..c5c9e64c224 100644
--- a/reactos/boot/bootdata/packages/reactos.dff
+++ b/reactos/boot/bootdata/packages/reactos.dff
@@ -41,6 +41,7 @@ base\applications\games\solitaire\sol.exe 1
base\applications\games\winemine\winemine.exe 1
base\applications\hh\hh.exe 1
base\applications\hostname\hostname.exe 1
+base\applications\logoff\logoff.exe 1
base\applications\msconfig\msconfig.exe 1
base\applications\network\arp\arp.exe 1
base\applications\network\route\route.exe 1