263 lines
7.6 KiB
C
Executable File
263 lines
7.6 KiB
C
Executable File
/*
|
|
* UltraDefrag - a powerful defragmentation tool for Windows NT.
|
|
* Copyright (c) 2007-2011 by Dmitri Arkhangelski (dmitriar@gmail.com).
|
|
* Copyright (c) 2010-2011 by Stefan Pendl (stefanpe@users.sourceforge.net).
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
/*
|
|
* UltraDefrag boot time (native) interface.
|
|
*/
|
|
|
|
#include "defrag_native.h"
|
|
|
|
/*
|
|
* We're releasing this module as a monolithic thing to
|
|
* prevent BSOD in case of missing UltraDefrag native libraries.
|
|
* Otherwise the following modules becomes critical for the Windows
|
|
* boot process: udefrag.dll, zenwinx.dll.
|
|
* We don't know how to build monolithic app on MinGW,
|
|
* but on Windows DDK this works fine.
|
|
*/
|
|
|
|
/**
|
|
* @brief Process Environment Block.
|
|
*/
|
|
PEB *peb = NULL;
|
|
|
|
/**
|
|
* @brief History of commands
|
|
* typed in interactive mode.
|
|
*/
|
|
winx_history history = {0};
|
|
|
|
/**
|
|
* @brief Defines whether the program
|
|
* must exit from interactive mode or not.
|
|
*/
|
|
int exit_flag = 0;
|
|
|
|
/* forward declarations */
|
|
static void set_dbg_log(char *name);
|
|
|
|
/**
|
|
* @brief Initializes the native application.
|
|
*/
|
|
static int NativeAppInit(PPEB Peb)
|
|
{
|
|
/*
|
|
* Initialize registry in case
|
|
* of smss.exe replacement.
|
|
*/
|
|
#ifdef USE_INSTEAD_SMSS
|
|
(void)NtInitializeRegistry(0/*FALSE*/); /* saves boot log etc. */
|
|
#endif
|
|
|
|
/*
|
|
* Since v4.3.0 this app is monolithic
|
|
* to reach the highest level of reliability.
|
|
* It was not reliable before because crashed
|
|
* the system in case of missing DLL's.
|
|
*/
|
|
if(winx_init_library(Peb) < 0)
|
|
return (-1);
|
|
|
|
/* start initial logging */
|
|
set_dbg_log("startup-phase");
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Handles boot in Windows Safe Mode.
|
|
* @return Nonzero value if safe mode is
|
|
* detected, zero otherwise.
|
|
*/
|
|
static int HandleSafeModeBoot(void)
|
|
{
|
|
int safe_mode;
|
|
|
|
/*
|
|
* In Windows Safe Mode the boot time defragmenter
|
|
* is absolutely useless, because it cannot display
|
|
* text on the screen in this mode.
|
|
*/
|
|
safe_mode = winx_windows_in_safe_mode();
|
|
/*
|
|
* In case of errors we'll assume that we're running in Safe Mode.
|
|
* To avoid a very unpleasant situation when ultradefrag works
|
|
* in background and nothing happens on the black screen.
|
|
*/
|
|
if(safe_mode > 0 || safe_mode < 0){
|
|
/* display yet a message, for debugging purposes */
|
|
winx_printf("In Windows Safe Mode this program is useless!\n");
|
|
/* if someone will see the message, a little delay will help him to read it */
|
|
short_dbg_delay();
|
|
winx_exit(0);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Native application entry point.
|
|
*/
|
|
void __stdcall NtProcessStartup(PPEB Peb)
|
|
{
|
|
int init_result;
|
|
/*
|
|
* No longer than MAX_LINE_WIDTH to ensure that escape and backspace
|
|
* keys will work properly with winx_prompt() function.
|
|
*/
|
|
char buffer[MAX_LINE_WIDTH + 1];
|
|
short wbuffer[MAX_LINE_WIDTH + 1];
|
|
int i;
|
|
|
|
/* initialize the program */
|
|
peb = Peb;
|
|
init_result = NativeAppInit(Peb);
|
|
|
|
/* display copyrights */
|
|
winx_print("\n\n");
|
|
winx_print(VERSIONINTITLE " boot time interface\n"
|
|
"Copyright (c) Dmitri Arkhangelski, 2007-2011.\n"
|
|
"Copyright (c) Stefan Pendl, 2010-2011.\n\n"
|
|
"UltraDefrag comes with ABSOLUTELY NO WARRANTY.\n\n"
|
|
"If something is wrong, hit F8 on startup\n"
|
|
"and select 'Last Known Good Configuration'\n"
|
|
"or execute 'CHKDSK {Drive:} /R /F'.\n\n");
|
|
|
|
/* handle initialization failure */
|
|
if(init_result < 0){
|
|
winx_print("Initialization failed!\n");
|
|
winx_print("Send bug report to the authors please.\n");
|
|
long_dbg_delay();
|
|
winx_exit(1);
|
|
}
|
|
|
|
/* handle safe mode boot */
|
|
if(HandleSafeModeBoot())
|
|
return;
|
|
|
|
/* check for the pending boot-off command */
|
|
if(ExecPendingBootOff()){
|
|
#ifndef USE_INSTEAD_SMSS
|
|
winx_printf("Good bye ...\n");
|
|
short_dbg_delay();
|
|
winx_exit(0);
|
|
#endif
|
|
}
|
|
|
|
/* initialize keyboards */
|
|
if(winx_kb_init() < 0){
|
|
winx_printf("Wait 10 seconds ...\n");
|
|
long_dbg_delay();
|
|
winx_exit(1);
|
|
}
|
|
|
|
/* prompt to exit */
|
|
winx_printf("\nPress any key to exit ");
|
|
for(i = 0; i < 5; i++){
|
|
if(winx_kbhit(1000) >= 0){
|
|
winx_printf("\nGood bye ...\n");
|
|
winx_exit(0);
|
|
}
|
|
//winx_printf("%c ",(char)('0' + 10 - i));
|
|
winx_printf(".");
|
|
}
|
|
winx_printf("\n\n");
|
|
|
|
/* process default boot time script */
|
|
ProcessScript(NULL);
|
|
|
|
/* start interactive mode */
|
|
winx_printf("\nInteractive mode:\nType 'help' for a list of supported commands.\n");
|
|
winx_printf("\nOnly the English keyboard layout is available.\n\n");
|
|
scripting_mode = 0;
|
|
abort_flag = 0;
|
|
winx_init_history(&history);
|
|
while(winx_prompt_ex("# ",buffer,MAX_LINE_WIDTH,&history) >= 0){
|
|
/* convert command to unicode */
|
|
if(_snwprintf(wbuffer,MAX_LINE_WIDTH,L"%hs",buffer) < 0){
|
|
winx_printf("Command line is too long!\n");
|
|
continue;
|
|
}
|
|
wbuffer[MAX_LINE_WIDTH] = 0;
|
|
|
|
/* execute command */
|
|
parse_command(wbuffer);
|
|
|
|
/* break on exit */
|
|
if(exit_flag)
|
|
return;
|
|
}
|
|
|
|
/* break on winx_prompt_ex() errors */
|
|
exit_handler(0,NULL,NULL);
|
|
}
|
|
|
|
/**
|
|
* @brief Sets debugging log path.
|
|
* @details Intended primarily to log
|
|
* debugging information during the
|
|
* native application startup.
|
|
*/
|
|
static void set_dbg_log(char *name)
|
|
{
|
|
wchar_t windir[MAX_PATH];
|
|
char *logpath = NULL;
|
|
int length;
|
|
wchar_t *unicode_path = NULL;
|
|
|
|
if(winx_query_env_variable(L"SystemRoot",windir,MAX_PATH) < 0){
|
|
winx_printf("\nset_dbg_log: cannot get %%windir%% path\n\n");
|
|
return;
|
|
}
|
|
|
|
logpath = winx_sprintf("%ws\\UltraDefrag\\logs\\boot-%s.log",windir,name);
|
|
if(logpath == NULL){
|
|
winx_printf("\nset_dbg_log: cannot build log path\n\n");
|
|
return;
|
|
}
|
|
|
|
length = strlen(logpath);
|
|
unicode_path = winx_heap_alloc((length + 1) * sizeof(wchar_t));
|
|
if(unicode_path == NULL){
|
|
winx_printf("\nset_dbg_log: cannot allocate %u bytes of memory",
|
|
(length + 1) * sizeof(wchar_t));
|
|
goto done;
|
|
}
|
|
|
|
if(_snwprintf(unicode_path,length + 1,L"%hs",logpath) < 0){
|
|
winx_printf("\nset_dbg_log: cannot convert log path to unicode\n\n");
|
|
goto done;
|
|
}
|
|
|
|
unicode_path[length] = 0;
|
|
if(winx_set_env_variable(L"UD_LOG_FILE_PATH",unicode_path) < 0){
|
|
winx_printf("\nset_dbg_log: cannot set %%UD_LOG_FILE_PATH%%\n\n");
|
|
goto done;
|
|
}
|
|
|
|
if(udefrag_set_log_file_path() < 0)
|
|
winx_printf("\nset_dbg_log: udefrag_set_log_file_path failed\n\n");
|
|
|
|
done:
|
|
if(logpath)
|
|
winx_heap_free(logpath);
|
|
if(unicode_path)
|
|
winx_heap_free(unicode_path);
|
|
}
|