1 /*
2  * This file is part of Siril, an astronomy image processor.
3  * Copyright (C) 2005-2011 Francois Meyer (dulle at free.fr)
4  * Copyright (C) 2012-2021 team free-astro (see more in AUTHORS file)
5  * Reference site is https://free-astro.org/index.php/Siril
6  *
7  * Siril is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * Siril is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with Siril. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #ifdef _WIN32
22 #undef _WIN32_WINNT
23 #define _WIN32_WINNT _WIN32_WINNT_WIN10
24 #include <windows.h>
25 #else
26 #include <string.h>
27 #include <errno.h>
28 #endif
29 #include <stdio.h>
30 
31 #ifndef S_ISLNK
32 #define S_ISLNK(x) 0
33 #endif
34 
35 #include "core/siril.h"
36 #include "core/proto.h"
37 #include "core/processing.h"
38 #include "io/sequence.h"
39 #include "io/conversion.h"
40 #include "io/image_format_fits.h"
41 #include "gui/progress_and_log.h"
42 
43 #include "FITS_symlink.h"
44 
45 #ifdef _WIN32
46 #define PATH_APPMODEUNLOCK      TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppModelUnlock" )
47 #define CLE_APPMODEUNLOCK_ADWDL TEXT("AllowDevelopmentWithoutDevLicense" )
48 #define CLE_APPMODEUNLOCK_AATA  TEXT("AllowAllTrustedApps" )
49 
read_registre_value(LPTSTR lpKeyName,LPTSTR lpPolicyPath)50 DWORD read_registre_value(LPTSTR lpKeyName, LPTSTR lpPolicyPath) {
51 	DWORD dwReturnKo = -1;
52 	HKEY hKey;
53 	LONG lResult;
54 	DWORD dwValue;
55 	DWORD dwSize = sizeof(dwValue);
56 
57 	lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpPolicyPath, 0, KEY_QUERY_VALUE,
58 			&hKey);
59 	if (lResult != ERROR_SUCCESS) {
60 		printf("RegOpenKeyEx KO\n");
61 		return dwReturnKo;
62 	}
63 
64 	lResult = RegQueryValueEx(hKey, lpKeyName, 0, NULL, (LPBYTE) & dwValue,
65 			&dwSize);
66 	RegCloseKey(hKey);
67 
68 	return (lResult == ERROR_SUCCESS) ? dwValue : dwReturnKo;
69 }
70 #endif
71 
test_if_symlink_is_ok()72 gboolean test_if_symlink_is_ok() {
73 #ifdef _WIN32
74 	// AllowDevelopmentWithoutDevLicense=1  and AllowAllTrustedApps = 1 if DevMode is enabled
75 	// AllowDevelopmentWithoutDevLicense=0  and AllowAllTrustedApps = 0 if DevMode is disabled
76 	DWORD cr = read_registre_value(CLE_APPMODEUNLOCK_ADWDL, PATH_APPMODEUNLOCK);
77 	if (cr != 1 ) {
78 		siril_log_color_message(_("You should enable the Developer Mode in order to create symbolic links "
79 				"instead of simply copying files.\n"), "salmon");
80 		return FALSE;
81 	}
82 	return TRUE;
83 #else
84 	return TRUE;
85 #endif
86 }
87 
symlink_uniq_file(gchar * src_filename,gchar * dest_filename,gboolean allow_symlink)88 int symlink_uniq_file(gchar *src_filename, gchar *dest_filename, gboolean allow_symlink) {
89 	int retval = 0;
90 
91 	/* remove already existing file to avoid error */
92 	GStatBuf dest_stat;
93 	if (g_lstat(dest_filename, &dest_stat) == 0) {
94 		g_unlink(dest_filename);
95 	}
96 
97 #ifdef _WIN32
98 	if (allow_symlink) {
99 		wchar_t *wsrc, *wdst;
100 
101 		wsrc = g_utf8_to_utf16(src_filename, -1, NULL, NULL, NULL);
102 		wdst = g_utf8_to_utf16(dest_filename, -1, NULL, NULL, NULL);
103 
104 		if (CreateSymbolicLinkW(wdst, wsrc, SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) == 0) {
105 			retval = copy_fits_from_file(src_filename, dest_filename);
106 		}
107 
108 		g_free(wsrc);
109 		g_free(wdst);
110 	} else {
111 		retval = copy_fits_from_file(src_filename, dest_filename);
112 	}
113 #else
114 	static gboolean warned = FALSE;
115 
116 	if (symlink(src_filename, dest_filename)) {
117 		char err[150];
118 		strerror_r(errno, err, 150);
119 		if (!warned) {
120 			siril_log_color_message(_("Symbolic link could not be made, copying the file. Error: %s\n"), "salmon", err);
121 			warned = TRUE;
122 		}
123 		retval = copy_fits_from_file(src_filename, dest_filename);
124 	}
125 #endif
126 	return retval;
127 }
128