Make fireflyshell drop a drive mapping ini file, so that the server can convert network drive letters to unc paths.

This commit is contained in:
Ron Pedde 2006-11-13 00:09:16 +00:00
parent c1ac15cd97
commit 16b323f024
4 changed files with 306 additions and 237 deletions

View File

@ -262,6 +262,7 @@ void scan_process_playlistlist(void) {
int scan_init(char **patharray) { int scan_init(char **patharray) {
int err=0; int err=0;
int index=0; int index=0;
char resolved_path[MAX_PATH];
DPRINTF(E_DBG,L_SCAN,"Starting scan_init\n"); DPRINTF(E_DBG,L_SCAN,"Starting scan_init\n");
@ -274,7 +275,8 @@ int scan_init(char **patharray) {
while((patharray[index] != NULL) && (!util_must_exit())) { while((patharray[index] != NULL) && (!util_must_exit())) {
DPRINTF(E_DBG,L_SCAN,"Scanning for MP3s in %s\n",patharray[index]); DPRINTF(E_DBG,L_SCAN,"Scanning for MP3s in %s\n",patharray[index]);
err=scan_path(patharray[index]); realpath(patharray[index],resolved_path);
err=scan_path(resolved_path);
index++; index++;
} }

View File

@ -28,6 +28,9 @@ static os_serviceflag = 0;
static pthread_t os_service_tid; static pthread_t os_service_tid;
static os_initialized=0; static os_initialized=0;
static pthread_mutex_t os_mutex=PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t os_mutex=PTHREAD_MUTEX_INITIALIZER;
static char *os_drive_maps[26];
static int os_maps_init=0;
/* Forwards */ /* Forwards */
static void _os_socket_startup(void); static void _os_socket_startup(void);
@ -37,6 +40,8 @@ static void _os_lock(void);
static void _os_unlock(void); static void _os_unlock(void);
static BOOL WINAPI _os_cancelhandler(DWORD dwCtrlType); static BOOL WINAPI _os_cancelhandler(DWORD dwCtrlType);
static void _os_phandle_dump(void); static void _os_phandle_dump(void);
char *_os_filepath(char *file);
extern int gettimeout(struct timeval end,struct timeval *timeoutp); extern int gettimeout(struct timeval end,struct timeval *timeoutp);
@ -76,7 +81,26 @@ char *os_w32_socket_states[] = {
*/ */
int os_init(int foreground, char *runas) { int os_init(int foreground, char *runas) {
int err; int err;
char *inifile;
char drive_buffer[4];
char drive_map[MAX_PATH];
int drive_letter;
inifile=_os_filepath("mapping.ini");
DPRINTF(E_LOG,L_MISC,"Building drive mapping table from %s\n",inifile);
for(drive_letter = 'a'; drive_letter <= 'z'; drive_letter++) {
sprintf(drive_buffer,"%c",drive_letter);
GetPrivateProfileString("mapping",drive_buffer,"",drive_map,MAX_PATH,inifile);
if(strlen(drive_map)) {
os_drive_maps[drive_letter - 'a'] = strdup(drive_map);
DPRINTF(E_LOG,L_MISC,"Mapped %c to %s\n",drive_letter,drive_map);
} else {
os_drive_maps[drive_letter - 'a'] = NULL;
}
}
os_maps_init=1;
free(inifile);
_os_socket_startup(); _os_socket_startup();
if(!os_initialized) { if(!os_initialized) {
@ -520,25 +544,37 @@ char *os_strerror (int error_no) {
* @returns path to config file (from static buffer) * @returns path to config file (from static buffer)
*/ */
char *os_configpath(void) { char *os_configpath(void) {
char drive[_MAX_DRIVE]; char *config_path = _os_filepath("mt-daapd.conf");
char dir[_MAX_DIR]; char *working_path = _os_filepath("");
char working_dir[_MAX_PATH];
GetModuleFileName(NULL,os_config_file,_MAX_PATH); strcpy(os_config_file,config_path);
_splitpath(os_config_file,drive,dir,NULL,NULL); free(config_path);
_makepath(os_config_file,drive,dir,"mt-daapd","conf");
_makepath(working_dir,drive,dir,NULL,NULL);
if(_chdir(working_dir) == -1) { if(_chdir(working_path) == -1) {
DPRINTF(E_LOG,L_MISC,"Could not chdir to %s... using c:\\\n",working_dir); DPRINTF(E_LOG,L_MISC,"Could not chdir to %s... using c:\\\n",working_path);
if(_chdir("c:\\") == -1) { if(_chdir("c:\\") == -1) {
DPRINTF(E_FATAL,L_MISC,"Could not chdir to c:\\... aborting\n"); DPRINTF(E_FATAL,L_MISC,"Could not chdir to c:\\... aborting\n");
} }
} }
free(working_path);
DPRINTF(E_DBG,L_MISC,"Using config file %s\n",os_config_file); DPRINTF(E_DBG,L_MISC,"Using config file %s\n",os_config_file);
return os_config_file; return os_config_file;
} }
char *_os_filepath(char *file) {
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char path[_MAX_PATH];
GetModuleFileName(NULL,path,_MAX_PATH);
_splitpath(path,drive,dir,NULL,NULL);
_makepath(path,drive,dir,NULL,NULL);
strcat(path,file);
return strdup(path);
}
/** /**
* get the path of the executable. Caller must free. * get the path of the executable. Caller must free.
* *
@ -616,7 +652,7 @@ void *os_loadlib(char **pe, char *path) {
void *retval; void *retval;
UINT old_mode; UINT old_mode;
old_mode = SetErrorMode(SEM_NOOPENFILEERRORBOX); old_mode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
retval = (void*)LoadLibrary(path); retval = (void*)LoadLibrary(path);
if(!retval) { if(!retval) {
if(pe) *pe = strdup(os_strerror(0)); if(pe) *pe = strdup(os_strerror(0));
@ -744,6 +780,7 @@ char *os_realpath(const char *pathname, char *resolved_path) {
char *ptr; char *ptr;
WCHAR utf16_rel_path[PATH_MAX+1]; WCHAR utf16_rel_path[PATH_MAX+1];
WCHAR utf16_path[PATH_MAX+1]; WCHAR utf16_path[PATH_MAX+1];
char *mapped_path;
/* need to take the utf-8 and convert to utf-16, then _fullpath, then back */ /* need to take the utf-8 and convert to utf-16, then _fullpath, then back */
util_utf8toutf16((unsigned char *)&utf16_rel_path,PATH_MAX * sizeof(WCHAR),(char*)pathname,(int)strlen(pathname)); util_utf8toutf16((unsigned char *)&utf16_rel_path,PATH_MAX * sizeof(WCHAR),(char*)pathname,(int)strlen(pathname));
@ -765,6 +802,15 @@ char *os_realpath(const char *pathname, char *resolved_path) {
resolved_path[strlen(resolved_path)-1] = '\x0'; resolved_path[strlen(resolved_path)-1] = '\x0';
} }
/* convert drive letter to unc path? */
if((resolved_path[0] != '\\')&&(os_maps_init)){
if((mapped_path = os_drive_maps[tolower(resolved_path[0]) - 'a'])) {
/* replace the x:\ with the path */
memmove(&resolved_path[strlen(mapped_path)],&resolved_path[3],strlen(resolved_path)-2); /* get the null */
memcpy(resolved_path,mapped_path,strlen(mapped_path));
}
}
return &resolved_path[0]; return &resolved_path[0];
} }

View File

@ -1,18 +1,18 @@
/* /*
*(C) 2006 Roku LLC *(C) 2006 Roku LLC
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License Version 2 as published * under the terms of the GNU General Public License Version 2 as published
* by the Free Software Foundation. * by the Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* without any warranty; without even the implied warranty of * without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. See the GNU General * merchantability or fitness for a particular purpose. See the GNU General
* Public License for more details. * Public License for more details.
* *
* Please read README.txt in the same directory as this source file for * Please read README.txt in the same directory as this source file for
* further license information. * further license information.
*/ */
#include "stdafx.h" #include "stdafx.h"
#include "resource.h" #include "resource.h"
@ -29,167 +29,188 @@ CAppModule _Module;
#define RUN_VALUE _T("FireflyShell") #define RUN_VALUE _T("FireflyShell")
Application::Application() Application::Application()
: m_dlg(NULL), m_server_events(&m_icon) : m_dlg(NULL), m_server_events(&m_icon)
{ {
CDosPath path = CDosPath::AppPath(); CDosPath path = CDosPath::AppPath();
SetCurrentDirectory(path.GetPathOnly()); SetCurrentDirectory(path.GetPathOnly());
CDosPath filename(_T("mt-daapd.conf")); CDosPath filename(_T("mt-daapd.conf"));
filename |= path; filename |= path;
m_config_path = filename.GetPath(); m_config_path = filename.GetPath();
ATLTRACE("Config path: %s\n", (const TCHAR *)m_config_path); ATLTRACE("Config path: %s\n", (const TCHAR *)m_config_path);
// We don't care if this fails. We can deal with that later. // Dump an ini file with drive mappings
m_service.Open(_T("Firefly Media Server")); CDosPath mapfile(_T("mapping.ini"));
mapfile |= path;
CheckCanConfigure(); TCHAR inbuffer[4];
TCHAR outbuffer[2048]; /* as max_path is unreliable */
DWORD size;
UNIVERSAL_NAME_INFO * puni = (UNIVERSAL_NAME_INFO *) &outbuffer;
m_unique_name = GenerateUniqueName(); for(int x='A'; x<='Z'; x++) {
m_registered_activation_message = ::RegisterWindowMessage(m_unique_name); wsprintf(inbuffer,_T("%c:\\"),x);
memset(outbuffer,0,sizeof(outbuffer));
size = sizeof(outbuffer);
WNetGetUniversalName(inbuffer,UNIVERSAL_NAME_INFO_LEVEL,outbuffer,
&size);
wsprintf(inbuffer,_T("%c"),x);
WritePrivateProfileString(_T("mapping"),inbuffer,puni->lpUniversalName,
mapfile.GetPath());
}
// We don't care if this fails. We can deal with that later.
m_service.Open(_T("Firefly Media Server"));
CheckCanConfigure();
m_unique_name = GenerateUniqueName();
m_registered_activation_message = ::RegisterWindowMessage(m_unique_name);
} }
Application::~Application() Application::~Application()
{ {
ATLASSERT(m_dlg == NULL); ATLASSERT(m_dlg == NULL);
} }
void Application::CheckCanConfigure() void Application::CheckCanConfigure()
{ {
IniFile ini(m_config_path); IniFile ini(m_config_path);
m_configurable = ini.IsWritable(); m_configurable = ini.IsWritable();
} }
int Application::Run(LPCTSTR lpstrCmdLine, int nCmdShow) int Application::Run(LPCTSTR lpstrCmdLine, int nCmdShow)
{ {
if (ActivatePreviousInstance(lpstrCmdLine, nCmdShow)) if (ActivatePreviousInstance(lpstrCmdLine, nCmdShow))
{ {
ATLTRACE(_T("Already running\n")); ATLTRACE(_T("Already running\n"));
return 0; return 0;
} }
CMessageLoop theLoop; CMessageLoop theLoop;
_Module.AddMessageLoop(&theLoop); _Module.AddMessageLoop(&theLoop);
if (!m_icon.Create()) if (!m_icon.Create())
{ {
ATLTRACE(_T("Icon creation failed!\n")); ATLTRACE(_T("Icon creation failed!\n"));
return 0; return 0;
} }
EnableServerEvents(true); EnableServerEvents(true);
if (ShowDialogAtStart(lpstrCmdLine, nCmdShow)) if (ShowDialogAtStart(lpstrCmdLine, nCmdShow))
Configure(false); Configure(false);
int nRet = theLoop.Run(); int nRet = theLoop.Run();
EnableServerEvents(false); EnableServerEvents(false);
m_icon.Destroy(); m_icon.Destroy();
_Module.RemoveMessageLoop(); _Module.RemoveMessageLoop();
return nRet; return nRet;
} }
void Application::Exit() void Application::Exit()
{ {
if (m_dlg) if (m_dlg)
{ {
m_dlg->DestroyWindow(); m_dlg->DestroyWindow();
} }
::PostQuitMessage(0); ::PostQuitMessage(0);
} }
void Application::Configure(bool move_window) void Application::Configure(bool move_window)
{ {
if (m_dlg) if (m_dlg)
{ {
m_dlg->ShowWindow(SW_RESTORE); m_dlg->ShowWindow(SW_RESTORE);
SetForegroundWindow(m_dlg->m_hWnd); SetForegroundWindow(m_dlg->m_hWnd);
} }
else else
{ {
CheckCanConfigure(); CheckCanConfigure();
// Other people may need to talk to the dialog while it exists. // Other people may need to talk to the dialog while it exists.
CMainDlg dlg(move_window); CMainDlg dlg(move_window);
m_dlg = &dlg; m_dlg = &dlg;
dlg.DoModal(); dlg.DoModal();
m_dlg = NULL; m_dlg = NULL;
} }
} }
void Application::StartService(HWND hwndParent) void Application::StartService(HWND hwndParent)
{ {
CWaitCursor wc; CWaitCursor wc;
ATLASSERT(m_service.CanControl()); ATLASSERT(m_service.CanControl());
if (!m_service.CanControl()) if (!m_service.CanControl())
return; return;
if (!m_service.StartAndWait()) if (!m_service.StartAndWait())
{ {
MessageBox(hwndParent, IDS_SERVERSTARTFAIL, MB_OK); MessageBox(hwndParent, IDS_SERVERSTARTFAIL, MB_OK);
} }
} }
void Application::StopService(HWND hwndParent) void Application::StopService(HWND hwndParent)
{ {
CWaitCursor wc; CWaitCursor wc;
ATLASSERT(m_service.CanControl()); ATLASSERT(m_service.CanControl());
if (!m_service.CanControl()) if (!m_service.CanControl())
return; return;
if (!m_service.StopAndWait()) if (!m_service.StopAndWait())
{ {
MessageBox(hwndParent, IDS_SERVERSTOPFAIL, MB_OK); MessageBox(hwndParent, IDS_SERVERSTOPFAIL, MB_OK);
} }
} }
void Application::RestartService(HWND hwndParent) void Application::RestartService(HWND hwndParent)
{ {
CWaitCursor wc; CWaitCursor wc;
StopService(hwndParent); StopService(hwndParent);
StartService(hwndParent); StartService(hwndParent);
} }
bool Application::ShowDialogAtStart(LPCTSTR cmdline, int nCmdShow) bool Application::ShowDialogAtStart(LPCTSTR cmdline, int nCmdShow)
{ {
if ((cmdline[0] == '-') && (cmdline[1] == 'q')) if ((cmdline[0] == '-') && (cmdline[1] == 'q'))
return false; return false;
switch (nCmdShow) switch (nCmdShow)
{ {
case SW_RESTORE: case SW_RESTORE:
case SW_SHOW: case SW_SHOW:
case SW_SHOWMAXIMIZED: case SW_SHOWMAXIMIZED:
case SW_SHOWNORMAL: case SW_SHOWNORMAL:
case SW_SHOWDEFAULT: case SW_SHOWDEFAULT:
case SW_MAX: case SW_MAX:
return true; return true;
default: default:
return false; return false;
} }
} }
BOOL CALLBACK Application::StaticWindowSearcher(HWND hwnd, LPARAM lparam) BOOL CALLBACK Application::StaticWindowSearcher(HWND hwnd, LPARAM lparam)
{ {
DWORD result; DWORD result;
LRESULT ok = ::SendMessageTimeout(hwnd, LRESULT ok = ::SendMessageTimeout(hwnd,
static_cast<UINT>(lparam), static_cast<UINT>(lparam),
0, 0, 0, 0,
SMTO_BLOCK | SMTO_BLOCK |
SMTO_ABORTIFHUNG, SMTO_ABORTIFHUNG,
200, 200,
&result); &result);
if (ok == 0) if (ok == 0)
return TRUE; // ignore this and continue return TRUE; // ignore this and continue
// If we get the magic response then we must have found our Window // If we get the magic response then we must have found our Window
// so we can give up. // so we can give up.
if (result == lparam) if (result == lparam)
return FALSE; return FALSE;
else else
return TRUE; return TRUE;
} }
bool Application::ActivatePreviousInstance(LPCTSTR lpstrCmdLine, int nCmdShow) bool Application::ActivatePreviousInstance(LPCTSTR lpstrCmdLine, int nCmdShow)
@ -202,27 +223,27 @@ bool Application::ActivatePreviousInstance(LPCTSTR lpstrCmdLine, int nCmdShow)
::ReleaseMutex(h); ::ReleaseMutex(h);
} }
// It seems that getting the other window to activate itself does // It seems that getting the other window to activate itself does
// actually work even though Windows anti-focus-stealing stuff // actually work even though Windows anti-focus-stealing stuff
// could try and stop it. // could try and stop it.
if (running && ShowDialogAtStart(lpstrCmdLine, nCmdShow)) if (running && ShowDialogAtStart(lpstrCmdLine, nCmdShow))
{ {
EnumWindows(StaticWindowSearcher, m_registered_activation_message); EnumWindows(StaticWindowSearcher, m_registered_activation_message);
return true; return true;
} }
return running; return running;
} }
CString Application::GenerateUniqueName() CString Application::GenerateUniqueName()
{ {
// We need to allow one instance to run per desktop. See // We need to allow one instance to run per desktop. See
// http://www.codeproject.com/cpp/avoidmultinstance.asp // http://www.codeproject.com/cpp/avoidmultinstance.asp
// First start with some application unique // First start with some application unique
CString s(_T("Firefly-67A72768-4154-417e-BFA0-FA9B50C342DE")); CString s(_T("Firefly-67A72768-4154-417e-BFA0-FA9B50C342DE"));
// Now append something desktop unique // Now append something desktop unique
DWORD len; DWORD len;
HDESK desktop = GetThreadDesktop(GetCurrentThreadId()); HDESK desktop = GetThreadDesktop(GetCurrentThreadId());
BOOL result = GetUserObjectInformation(desktop, UOI_NAME, NULL, 0, &len); BOOL result = GetUserObjectInformation(desktop, UOI_NAME, NULL, 0, &len);
@ -244,129 +265,129 @@ CString Application::GenerateUniqueName()
void Application::EnableServerEvents(bool b) void Application::EnableServerEvents(bool b)
{ {
if (b) if (b)
m_server_events.Start(); m_server_events.Start();
else else
m_server_events.Stop(); m_server_events.Stop();
} }
CString Application::MakeRunKeyValue() CString Application::MakeRunKeyValue()
{ {
CString required_path("\""); CString required_path("\"");
required_path += CDosPath::AppPath().GetPath(); required_path += CDosPath::AppPath().GetPath();
required_path += "\" -q"; required_path += "\" -q";
return required_path; return required_path;
} }
void Application::EnableAutoStart(HWND hwnd, bool enable) void Application::EnableAutoStart(HWND hwnd, bool enable)
{ {
// First let's control the service. // First let's control the service.
int required_startup = enable ? SERVICE_AUTO_START : SERVICE_DISABLED; int required_startup = enable ? SERVICE_AUTO_START : SERVICE_DISABLED;
if (m_service.GetStartup() != required_startup) if (m_service.GetStartup() != required_startup)
{ {
if (!m_service.ConfigureStartup(required_startup)) if (!m_service.ConfigureStartup(required_startup))
{ {
MessageBox(hwnd, IDS_FAILED_CONFIGURE_SERVICE, MB_OK); MessageBox(hwnd, IDS_FAILED_CONFIGURE_SERVICE, MB_OK);
} }
} }
// Now let's set up the Run key. // Now let's set up the Run key.
HKEY hkey; HKEY hkey;
LONG result = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, RUN_KEY, 0, KEY_SET_VALUE | STANDARD_RIGHTS_WRITE, &hkey); LONG result = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, RUN_KEY, 0, KEY_SET_VALUE | STANDARD_RIGHTS_WRITE, &hkey);
if (result == ERROR_SUCCESS) if (result == ERROR_SUCCESS)
{ {
if (enable) if (enable)
{ {
// We need to quote it because the path may contain spaces. // We need to quote it because the path may contain spaces.
CString str = MakeRunKeyValue(); CString str = MakeRunKeyValue();
result = RegSetValueEx(hkey, RUN_VALUE, 0UL, REG_SZ, reinterpret_cast<LPCBYTE>(static_cast<LPCTSTR>(str)), (str.GetLength() + 1) * sizeof(TCHAR)); result = RegSetValueEx(hkey, RUN_VALUE, 0UL, REG_SZ, reinterpret_cast<LPCBYTE>(static_cast<LPCTSTR>(str)), (str.GetLength() + 1) * sizeof(TCHAR));
} }
else else
{ {
result = RegDeleteValue(hkey, RUN_VALUE); result = RegDeleteValue(hkey, RUN_VALUE);
if (result == ERROR_FILE_NOT_FOUND) if (result == ERROR_FILE_NOT_FOUND)
result = 0; result = 0;
} }
if (result != ERROR_SUCCESS) if (result != ERROR_SUCCESS)
{ {
ATLTRACE("Error:%u\n", result); ATLTRACE("Error:%u\n", result);
MessageBox(hwnd, IDS_FAILED_CONFIGURE_STARTUP, MB_OK); MessageBox(hwnd, IDS_FAILED_CONFIGURE_STARTUP, MB_OK);
} }
} }
} }
int Application::IsAutoStartEnabled() const int Application::IsAutoStartEnabled() const
{ {
// Look at the service // Look at the service
int service_result = 2; int service_result = 2;
switch (m_service.GetStartup()) switch (m_service.GetStartup())
{ {
case SERVICE_AUTO_START: case SERVICE_AUTO_START:
service_result = true; service_result = true;
break; break;
case SERVICE_DISABLED: case SERVICE_DISABLED:
service_result = false; service_result = false;
break; break;
} }
// Look at the Run key // Look at the Run key
int run_result = 2; int run_result = 2;
HKEY hkey; HKEY hkey;
if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, RUN_KEY, 0, KEY_QUERY_VALUE | STANDARD_RIGHTS_READ, &hkey) == ERROR_SUCCESS) if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, RUN_KEY, 0, KEY_QUERY_VALUE | STANDARD_RIGHTS_READ, &hkey) == ERROR_SUCCESS)
{ {
DWORD dwType, cbData; DWORD dwType, cbData;
TCHAR buffer[_MAX_PATH + 1]; TCHAR buffer[_MAX_PATH + 1];
cbData = (_MAX_PATH + 1) * sizeof(TCHAR); cbData = (_MAX_PATH + 1) * sizeof(TCHAR);
if (::RegQueryValueEx(hkey, RUN_VALUE, NULL, &dwType, reinterpret_cast<LPBYTE>(buffer), &cbData) == ERROR_SUCCESS) if (::RegQueryValueEx(hkey, RUN_VALUE, NULL, &dwType, reinterpret_cast<LPBYTE>(buffer), &cbData) == ERROR_SUCCESS)
{ {
CString path(buffer, cbData - sizeof(TCHAR)); CString path(buffer, cbData - sizeof(TCHAR));
ATLTRACE("Registry run key path: %s\n", (const TCHAR *)path); ATLTRACE("Registry run key path: %s\n", (const TCHAR *)path);
if (path == MakeRunKeyValue()) if (path == MakeRunKeyValue())
run_result = true; run_result = true;
else else
{ {
// It's there - but it isn't us that it will start. // It's there - but it isn't us that it will start.
run_result = 2; run_result = 2;
} }
} }
else else
{ {
// The key doesn't exist. // The key doesn't exist.
run_result = false; run_result = false;
} }
} }
else else
{ {
run_result = false; run_result = false;
} }
// If the answers agree then return them. Otherwise we're indeterminate. // If the answers agree then return them. Otherwise we're indeterminate.
if (run_result == service_result) if (run_result == service_result)
return run_result; return run_result;
else else
return 2; return 2;
} }
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow) int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{ {
// this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used // this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used
::DefWindowProc(NULL, 0, 0, 0L); ::DefWindowProc(NULL, 0, 0, 0L);
AtlInitCommonControls(ICC_BAR_CLASSES); // add flags to support other controls AtlInitCommonControls(ICC_BAR_CLASSES); // add flags to support other controls
HRESULT hRes = _Module.Init(NULL, hInstance); HRESULT hRes = _Module.Init(NULL, hInstance);
ATLASSERT(SUCCEEDED(hRes)); ATLASSERT(SUCCEEDED(hRes));
int nRet; int nRet;
{ {
// Application object is destroyed prior to undoing everything above. // Application object is destroyed prior to undoing everything above.
Application app; Application app;
nRet = app.Run(lpstrCmdLine, nCmdShow); nRet = app.Run(lpstrCmdLine, nCmdShow);
} }
_Module.Term(); _Module.Term();
return nRet; return nRet;
} }

View File

@ -31,7 +31,7 @@
Name="VCCustomBuildTool"/> Name="VCCustomBuildTool"/>
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="version.lib" AdditionalDependencies="version.lib mpr.lib"
OutputFile="$(OutDir)/FireflyShell.exe" OutputFile="$(OutDir)/FireflyShell.exe"
LinkIncremental="2" LinkIncremental="2"
GenerateDebugInformation="TRUE" GenerateDebugInformation="TRUE"
@ -77,7 +77,7 @@
Name="VCCustomBuildTool"/> Name="VCCustomBuildTool"/>
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="version.lib" AdditionalDependencies="version.lib mpr.lib"
OutputFile="$(OutDir)/FireflyShell.exe" OutputFile="$(OutDir)/FireflyShell.exe"
LinkIncremental="1" LinkIncremental="1"
GenerateDebugInformation="TRUE" GenerateDebugInformation="TRUE"