⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 explorer.cpp

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
const Icon& IconCache::add(HICON hIcon, ICON_TYPE type)
{
	int id = ++s_next_id;

	return _icons[id] = Icon(type, id, hIcon);
}

const Icon&	IconCache::add(int sys_idx/*, ICON_TYPE type=IT_SYSCACHE*/)
{
	int id = ++s_next_id;

	return _icons[id] = SysCacheIcon(id, sys_idx);
}

const Icon& IconCache::get_icon(int id)
{
	return _icons[id];
}

void IconCache::free_icon(int icon_id)
{
	IconMap::iterator found = _icons.find(icon_id);

	if (found != _icons.end()) {
		Icon& icon = found->second;

		if (icon.destroy())
			_icons.erase(found);
	}
}


ResString::ResString(UINT nid)
{
	TCHAR buffer[BUFFER_LEN];

	int len = LoadString(g_Globals._hInstance, nid, buffer, sizeof(buffer)/sizeof(TCHAR));

	super::assign(buffer, len);
}


ResIcon::ResIcon(UINT nid)
{
	_hicon = LoadIcon(g_Globals._hInstance, MAKEINTRESOURCE(nid));
}

SmallIcon::SmallIcon(UINT nid)
{
	_hicon = (HICON)LoadImage(g_Globals._hInstance, MAKEINTRESOURCE(nid), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
}

ResIconEx::ResIconEx(UINT nid, int w, int h)
{
	_hicon = (HICON)LoadImage(g_Globals._hInstance, MAKEINTRESOURCE(nid), IMAGE_ICON, w, h, LR_SHARED);
}


void SetWindowIcon(HWND hwnd, UINT nid)
{
	HICON hIcon = ResIcon(nid);
	(void)Window_SetIcon(hwnd, ICON_BIG, hIcon);

	HICON hIconSmall = SmallIcon(nid);
	(void)Window_SetIcon(hwnd, ICON_SMALL, hIconSmall);
}


ResBitmap::ResBitmap(UINT nid)
{
	_hBmp = LoadBitmap(g_Globals._hInstance, MAKEINTRESOURCE(nid));
}


#ifndef ROSSHELL

void explorer_show_frame(int cmdShow, LPTSTR lpCmdLine)
{
	ExplorerCmd cmd;

	if (g_Globals._hMainWnd) {
		if (IsIconic(g_Globals._hMainWnd))
			ShowWindow(g_Globals._hMainWnd, SW_RESTORE);
		else
			SetForegroundWindow(g_Globals._hMainWnd);

		return;
	}

	g_Globals._prescan_nodes = false;

	XMLPos explorer_options = g_Globals.get_cfg("general/explorer");
	XS_String mdiStr = XMLString(explorer_options, "mdi");

	 // If there isn't yet the "mdi" setting in the configuration, display MDI/SDI dialog.
	if (mdiStr.empty())
		Dialog::DoModal(IDD_MDI_SDI, WINDOW_CREATOR(MdiSdiDlg), g_Globals._hwndDesktop);

	 // Now read the MDI attribute again and interpret it as boolean value.
	cmd._mdi = XMLBool(explorer_options, "mdi", true);

	cmd._cmdShow = cmdShow;

	 // parse command line options, which may overwrite the MDI flag
	if (lpCmdLine)
		cmd.ParseCmdLine(lpCmdLine);

	 // create main window
	MainFrameBase::Create(cmd);
}

bool ExplorerCmd::ParseCmdLine(LPCTSTR lpCmdLine)
{
	bool ok = true;

	LPCTSTR b = lpCmdLine;
	LPCTSTR p = b;

	while(*b) {
		 // remove leading space
		while(_istspace((unsigned)*b))
			++b;

		p = b;

		bool quote = false;

		 // options are separated by ','
		for(; *p; ++p) {
			if (*p == '"')	// Quote characters may appear at any position in the command line.
				quote = !quote;
			else if (*p==',' && !quote)
				break;
		}

		if (p > b) {
			int l = p - b;

			 // remove trailing space
			while(l>0 && _istspace((unsigned)b[l-1]))
				--l;

			if (!EvaluateOption(String(b, l)))
				ok = false;

			if (*p)
				++p;

			b = p;
		}
	}

	return ok;
}

bool ExplorerCmd::EvaluateOption(LPCTSTR option)
{
	String opt_str;

	 // Remove quote characters, as they are evaluated at this point.
	for(; *option; ++option)
		if (*option != '"')
			opt_str += *option;

	option = opt_str;

	if (option[0] == '/') {
		++option;

		 // option /e for windows in explorer mode
		if (!_tcsicmp(option, TEXT("e")))
			_flags |= OWM_EXPLORE;
		 // option /root for rooted explorer windows
		else if (!_tcsicmp(option, TEXT("root")))
			_flags |= OWM_ROOTED;
		 // non-standard options: /mdi, /sdi
		else if (!_tcsicmp(option, TEXT("mdi")))
			_mdi = true;
		else if (!_tcsicmp(option, TEXT("sdi")))
			_mdi = false;
		else
			return false;
	} else {
		if (!_path.empty())
			return false;

		_path = opt_str;
	}

	return true;
}

bool ExplorerCmd::IsValidPath() const
{
	if (!_path.empty()) {
		DWORD attribs = GetFileAttributes(_path);

		if (attribs!=INVALID_FILE_ATTRIBUTES && (attribs&FILE_ATTRIBUTE_DIRECTORY))
			return true;	// file system path
		else if (*_path==':' && _path.at(1)==':')
			return true;	// text encoded IDL
	}

	return false;
}

#else

void explorer_show_frame(int cmdShow, LPTSTR lpCmdLine)
{
	if (!lpCmdLine)
		lpCmdLine = TEXT("explorer.exe");

	launch_file(GetDesktopWindow(), lpCmdLine, cmdShow);
}

#endif


PopupMenu::PopupMenu(UINT nid)
{
	HMENU hMenu = LoadMenu(g_Globals._hInstance, MAKEINTRESOURCE(nid));
	_hmenu = GetSubMenu(hMenu, 0);
}


 /// "About Explorer" Dialog
struct ExplorerAboutDlg : public
			CtlColorParent<
				OwnerDrawParent<Dialog>
			>
{
	typedef CtlColorParent<
				OwnerDrawParent<Dialog>
			> super;

	ExplorerAboutDlg(HWND hwnd)
	 :	super(hwnd)
	{
		SetWindowIcon(hwnd, IDI_REACTOS);

		new FlatButton(hwnd, IDOK);

		_hfont = CreateFont(20, 0, 0, 0, FW_BOLD, TRUE, 0, 0, 0, 0, 0, 0, 0, TEXT("Sans Serif"));
		new ColorStatic(hwnd, IDC_ROS_EXPLORER, RGB(32,32,128), 0, _hfont);

		new HyperlinkCtrl(hwnd, IDC_WWW);

		FmtString ver_txt(ResString(IDS_EXPLORER_VERSION_STR), (LPCTSTR)ResString(IDS_VERSION_STR));
		SetWindowText(GetDlgItem(hwnd, IDC_VERSION_TXT), ver_txt);

		HWND hwnd_winver = GetDlgItem(hwnd, IDC_WIN_VERSION);
		SetWindowText(hwnd_winver, get_windows_version_str());
		SetWindowFont(hwnd_winver, GetStockFont(DEFAULT_GUI_FONT), FALSE);

		CenterWindow(hwnd);
	}

	~ExplorerAboutDlg()
	{
		DeleteObject(_hfont);
	}

	LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
	{
		switch(nmsg) {
		  case WM_PAINT:
			Paint();
			break;

		  default:
			return super::WndProc(nmsg, wparam, lparam);
		}

		return 0;
	}

	void Paint()
	{
		PaintCanvas canvas(_hwnd);

		HICON hicon = (HICON) LoadImage(g_Globals._hInstance, MAKEINTRESOURCE(IDI_REACTOS_BIG), IMAGE_ICON, 0, 0, LR_SHARED);

		DrawIconEx(canvas, 20, 10, hicon, 0, 0, 0, 0, DI_NORMAL);
	}

protected:
	HFONT	_hfont;
};

void explorer_about(HWND hwndParent)
{
	Dialog::DoModal(IDD_ABOUT_EXPLORER, WINDOW_CREATOR(ExplorerAboutDlg), hwndParent);
}


static void InitInstance(HINSTANCE hInstance)
{
	CONTEXT("InitInstance");

	setlocale(LC_COLLATE, "");	// set collating rules to local settings for compareName

#ifndef ROSSHELL
	 // register frame window class
	g_Globals._hframeClass = IconWindowClass(CLASSNAME_FRAME,IDI_EXPLORER);

	 // register child window class
	WindowClass(CLASSNAME_CHILDWND, CS_CLASSDC|CS_DBLCLKS|CS_VREDRAW).Register();

	 // register tree window class
	WindowClass(CLASSNAME_WINEFILETREE, CS_CLASSDC|CS_DBLCLKS|CS_VREDRAW).Register();
#endif

	g_Globals._cfStrFName = RegisterClipboardFormat(CFSTR_FILENAME);
}


int explorer_main(HINSTANCE hInstance, LPTSTR lpCmdLine, int cmdShow)
{
	CONTEXT("explorer_main");

	 // initialize Common Controls library
	CommonControlInit usingCmnCtrl;

	try {
		InitInstance(hInstance);
	} catch(COMException& e) {
		HandleException(e, GetDesktopWindow());
		return -1;
	}

#ifndef ROSSHELL
	if (cmdShow != SW_HIDE) {
/*	// don't maximize if being called from the ROS desktop
		if (cmdShow == SW_SHOWNORMAL)
				///@todo read window placement from registry
			cmdShow = SW_MAXIMIZE;
*/

		explorer_show_frame(cmdShow, lpCmdLine);
	}
#endif

	return Window::MessageLoop();
}


 // MinGW does not provide a Unicode startup routine, so we have to implement an own.
#if defined(__MINGW32__) && defined(UNICODE)

#define _tWinMain wWinMain
int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int);

int main(int argc, char* argv[])
{
	CONTEXT("main");

	STARTUPINFO startupinfo;
	int nShowCmd = SW_SHOWNORMAL;

	GetStartupInfo(&startupinfo);

	if (startupinfo.dwFlags & STARTF_USESHOWWINDOW)
		nShowCmd = startupinfo.wShowWindow;

	LPWSTR cmdline = GetCommandLineW();

	while(*cmdline && !_istspace((unsigned)*cmdline))
		++cmdline;

	while(_istspace((unsigned)*cmdline))
		++cmdline;

	return wWinMain(GetModuleHandle(NULL), 0, cmdline, nShowCmd);
}

#endif	// __MINGW && UNICODE


static bool SetShellReadyEvent(LPCTSTR evtName)
{
	HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, evtName);
	if (!hEvent)
		return false;

	SetEvent(hEvent);
	CloseHandle(hEvent);

	return true;
}


int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd)
{
	CONTEXT("WinMain()");

	BOOL any_desktop_running = IsAnyDesktopRunning();

	BOOL startup_desktop;

	 // strip extended options from the front of the command line
	String ext_options;

	while(*lpCmdLine == '-') {
		while(*lpCmdLine && !_istspace((unsigned)*lpCmdLine))
			ext_options += *lpCmdLine++;

		while(_istspace((unsigned)*lpCmdLine))
			++lpCmdLine;
	}

	 // command line option "-install" to replace previous shell application with ROS Explorer
	if (_tcsstr(ext_options,TEXT("-install"))) {
		 // install ROS Explorer into the registry
		TCHAR path[MAX_PATH];

		int l = GetModuleFileName(0, path, COUNTOF(path));
		if (l) {
			HKEY hkey;

			if (!RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), &hkey)) {

				///@todo save previous shell application in config file

				RegSetValueEx(hkey, TEXT("Shell"), 0, REG_SZ, (LPBYTE)path, l*sizeof(TCHAR));
				RegCloseKey(hkey);
			}

			if (!RegOpenKey(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), &hkey)) {

				///@todo save previous shell application in config file

				RegSetValueEx(hkey, TEXT("Shell"), 0, REG_SZ, (LPBYTE)TEXT(""), l*sizeof(TCHAR));
				RegCloseKey(hkey);
			}
		}

		HWND shellWindow = GetShellWindow();

		if (shellWindow) {
			DWORD pid;

			 // terminate shell process for NT like systems
			GetWindowThreadProcessId(shellWindow, &pid);
			HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);

			 // On Win 9x it's sufficient to destroy the shell window.
			DestroyWindow(shellWindow);

			if (TerminateProcess(hProcess, 0))
				WaitForSingleObject(hProcess, INFINITE);

			CloseHandle(hProcess);
		}

		startup_desktop = TRUE;
	} else {
		 // create desktop window and task bar only, if there is no other shell and we are
		 // the first explorer instance
		 // MS Explorer looks additionally into the registry entry HKCU\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\shell,
		 // to decide wether it is currently configured as shell application.
		startup_desktop = !any_desktop_running;
	}


	bool autostart = !any_desktop_running;

	 // disable autostart if the SHIFT key is pressed
	if (GetAsyncKeyState(VK_SHIFT) < 0)
		autostart = false;

#ifdef _DEBUG	//MF: disabled for debugging
	autostart = false;
#endif

	 // If there is given the command line option "-desktop", create desktop window anyways
	if (_tcsstr(ext_options,TEXT("-desktop")))
		startup_desktop = TRUE;
#ifndef ROSSHELL
	else if (_tcsstr(ext_options,TEXT("-nodesktop")))
		startup_desktop = FALSE;

	 // Don't display cabinet window in desktop mode
	if (startup_desktop && !_tcsstr(ext_options,TEXT("-explorer")))
		nShowCmd = SW_HIDE;
#endif

	if (_tcsstr(ext_options,TEXT("-noautostart")))
		autostart = false;
	else if (_tcsstr(ext_options,TEXT("-autostart")))
		autostart = true;

#ifndef __WINE__
	if (_tcsstr(ext_options,TEXT("-console"))) {
		AllocConsole();

		_dup2(_open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE), _O_RDONLY), 0);
		_dup2(_open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), 0), 1);
		_dup2(_open_osfhandle((long)GetStdHandle(STD_ERROR_HANDLE), 0), 2);

		g_Globals._log = _fdopen(1, "w");
		setvbuf(g_Globals._log, 0, _IONBF, 0);

		LOG(TEXT("starting explorer debug log\n"));
	}
#endif


	if (startup_desktop) {
		 // hide the XP login screen (Credit to Nicolas Escuder)
		 // another undocumented event: "Global\\msgina: ReturnToWelcome"
		if (!SetShellReadyEvent(TEXT("msgina: ShellReadyEvent")))
			SetShellReadyEvent(TEXT("Global\\msgina: ShellReadyEvent"));
	}
#ifdef ROSSHELL
	else
		return 0;	// no shell to launch, so exit immediatelly
#endif


	if (!any_desktop_running) {
		 // launch the shell DDE server
		if (g_SHDOCVW_ShellDDEInit)
			(*g_SHDOCVW_ShellDDEInit)(TRUE);
	}


	bool use_gdb_stub = false;	// !IsDebuggerPresent();

	if (_tcsstr(ext_options,TEXT("-debug")))
		use_gdb_stub = true;

	if (_tcsstr(ext_options,TEXT("-break"))) {
		LOG(TEXT("debugger breakpoint"));
#ifdef _MSC_VER
		__asm int 3
#else
		asm("int3");
#endif
	}

	 // activate GDB remote debugging stub if no other debugger is running
	if (use_gdb_stub) {
		LOG(TEXT("waiting for debugger connection...\n"));

		initialize_gdb_stub();
	}

	g_Globals.init(hInstance);

	 // initialize COM and OLE before creating the desktop window
	OleInit usingCOM;

	 // init common controls library
	CommonControlInit usingCmnCtrl;

	g_Globals.read_persistent();

	if (startup_desktop) {
		WaitCursor wait;

		g_Globals._desktops.init();

		g_Globals._hwndDesktop = DesktopWindow::Create();
#ifdef _USE_HDESK
		g_Globals._desktops.get_current_Desktop()->_hwndDesktop = g_Globals._hwndDesktop;
#endif
	}

	Thread* pSSOThread = NULL;

	if (startup_desktop) {
		 // launch SSO thread to allow message processing independent from the explorer main thread
		pSSOThread = new SSOThread;
		pSSOThread->Start();
	}

	/**TODO launching autostart programs can be moved into a background thread. */
	if (autostart) {
		const char* argv[] = {"", "s"};	// call startup routine in SESSION_START mode
		startup(2, argv);
	}

#ifndef ROSSHELL
	if (g_Globals._hwndDesktop)
		g_Globals._desktop_mode = true;
#endif


	int ret = explorer_main(hInstance, lpCmdLine, nShowCmd);


	 // write configuration file
	g_Globals.write_persistent();

	if (pSSOThread) {
		pSSOThread->Stop();
		delete pSSOThread;
	}

	if (!any_desktop_running) {
		 // shutdown the shell DDE server
		if (g_SHDOCVW_ShellDDEInit)
			(*g_SHDOCVW_ShellDDEInit)(FALSE);
	}

	return ret;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -