1 //
2 // Copyright (C) 2001-2013 Graeme Walker <graeme_walker@users.sourceforge.net>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // dir_win32.cpp
19 //
20 
21 #include "gdef.h"
22 #include "gconvert.h"
23 #include <shlwapi.h>
24 #include <shlobj.h>
25 
26 #ifndef SHGFP_TYPE_CURRENT
27 #define SHGFP_TYPE_CURRENT 0
28 #endif
29 #ifndef CSIDL_PROGRAM_FILES
30 #define CSIDL_PROGRAM_FILES 38
31 #endif
32 
33 #include "dir.h"
34 #include "gfile.h"
35 #include "gpath.h"
36 #include "glog.h"
37 #include <stdexcept>
38 
windows()39 G::Path Dir::windows()
40 {
41 	char buffer[MAX_PATH] = { 0 } ;
42 	unsigned int n = ::GetWindowsDirectoryA( buffer , MAX_PATH ) ;
43 	if( n == 0 || n > MAX_PATH )
44 		throw std::runtime_error( "cannot determine the windows directory" ) ;
45 	return G::Path( std::string(buffer,n) ) ;
46 }
47 
dotexe()48 std::string Dir::dotexe()
49 {
50 	return ".exe" ;
51 }
52 
os_install()53 G::Path Dir::os_install()
54 {
55 	return special("programs") + "emailrelay" ;
56 }
57 
os_gui(const G::Path & base)58 G::Path Dir::os_gui( const G::Path & base )
59 {
60 	return base + "emailrelay-gui.exe" ;
61 }
62 
os_icon(const G::Path & base)63 G::Path Dir::os_icon( const G::Path & base )
64 {
65 	return os_server( base ) ; // icon is a resource in the exe
66 }
67 
os_server(const G::Path & base)68 G::Path Dir::os_server( const G::Path & base )
69 {
70 	return base + "emailrelay.exe" ;
71 }
72 
os_config()73 G::Path Dir::os_config()
74 {
75 	return special("programs") + "emailrelay" ;
76 }
77 
os_spool()78 G::Path Dir::os_spool()
79 {
80 	return windows() + "system32" + "spool" + "emailrelay" ;
81 }
82 
os_pid(const G::Path & config_dir)83 G::Path Dir::os_pid( const G::Path & config_dir )
84 {
85 	return config_dir ;
86 }
87 
os_boot()88 G::Path Dir::os_boot()
89 {
90 	// empty implies no access (see call to Boot::able() in pages.cpp),
91 	// so the default has to be a bogus value
92 	return "services" ;
93 }
94 
os_bootcopy(const G::Path &,const G::Path &)95 G::Path Dir::os_bootcopy( const G::Path & , const G::Path & )
96 {
97 	return G::Path() ;
98 }
99 
cwd()100 G::Path Dir::cwd()
101 {
102 	DWORD n = ::GetCurrentDirectoryA( 0 , NULL ) ;
103 	char * buffer = new char [n+2U] ;
104 	buffer[0] = '\0' ;
105 	n = ::GetCurrentDirectoryA( n+1U , buffer ) ;
106 	std::string dir( buffer , n ) ;
107 	delete [] buffer ;
108 	if( n == 0U )
109 		throw std::runtime_error( "cannot determine the current working directory" ) ;
110 	return G::Path( dir ) ;
111 }
112 
113 namespace
114 {
special_id(const std::string & type)115 	int special_id( const std::string & type )
116 	{
117 		if( type == "desktop" ) return CSIDL_DESKTOPDIRECTORY ;
118 		if( type == "menu" ) return CSIDL_PROGRAMS ;
119 		if( type == "login" ) return CSIDL_STARTUP ;
120 		throw std::runtime_error("internal error") ;
121 		return 0 ;
122 	}
123 }
124 
special(const std::string & type)125 G::Path Dir::special( const std::string & type )
126 {
127 	if( type == "programs" )
128 	{
129 		char buffer[MAX_PATH] = { 0 } ;
130 		bool ok = S_OK == ::SHGetFolderPathA( NULL , CSIDL_PROGRAM_FILES , NULL , SHGFP_TYPE_CURRENT , buffer ) ;
131 		return ok ? G::Path(buffer) : G::Path("c:/program files") ;
132 	}
133 	else
134 	{
135 		char buffer[MAX_PATH] = { 0 } ;
136 		bool ok = TRUE == ::SHGetSpecialFolderPathA( NULL , buffer , special_id(type) , FALSE ) ;
137 		std::string result = ok ? std::string(buffer) : std::string() ;
138 		G::Path default_ = envPath("USERPROFILE",envPath("HOME")) ;
139 		return result.empty() ? default_ : G::Path(result) ;
140 	}
141 }
142 
home()143 G::Path Dir::home()
144 {
145 	return envPath( "USERPROFILE" , envPath( "HOME" , desktop() ) ) ;
146 }
147 
148 /// \file dir_win32.cpp
149