aboutsummaryrefslogtreecommitdiff
path: root/Src/Winamp/burn.cpp
blob: d1a6cc8d484bb6e7dc459ead3638b1628d258de1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/** (c) Nullsoft, Inc.         C O N F I D E N T I A L
 ** Filename: 
 ** Project:
 ** Description:
 ** Author:
 ** Created:
 **/
#include "main.h"
#include "resource.h"
#include <windows.h>
#include <strsafe.h>
#include <time.h>
#include <math.h>

#include "./api.h"
#include "./wa_ipc.h"
#include "../nu/ns_wc.h"
#include "../nu/AutoWide.h"
#include "../Agave/Language/api_language.h"
#include <api/service/waservicefactory.h>
#ifdef BURN_SUPPORT
#include "../primo/obj_primo.h"
#include "../burnlib/burnlib.h"

#endif

static void code(long* v, long* k)
{
	unsigned long y = v[0], z = v[1], sum = 0, delta = 0x9e3779b9, n = 32 ;  /* key schedule constant*/
	while (n-- > 0)
	{                                       /* basic cycle start */
		sum += delta;
		y += ((z << 4) + k[0]) ^ (z + sum) ^ ((z >> 5) + k[1]);
		z += ((y << 4) + k[2]) ^ (y + sum) ^ ((y >> 5) + k[3]); /* end cycle */
	}
	v[0] = y; v[1] = z;
}

int getRegVer(HWND waWnd)
{
	int *x = (int*)malloc(32);
	long s[3];
	long ss[2] = {(long)GetTickCount64(), (long)((int)x + (int)s)};
	long tealike_key[4] = { 31337, 0xf00d, 0xdead, 0xbeef};
	free(x);
	s[0] = ss[0];
	s[1] = ss[1];
	s[2] = 0;

	SendMessageW(waWnd, WM_WA_IPC, (WPARAM)s, IPC_GETREGISTEREDVERSION);
	code(ss, tealike_key);
	return (memcmp(s, ss, 8)) ? 0 : s[2];
}

#ifdef BURN_SUPPORT
int burn_start(burnCDStruct *param)
{
	char buf[MAX_PATH] = "\"";
	STARTUPINFO si = {sizeof(si), };
	PROCESS_INFORMATION pi;
	GetModuleFileName(NULL, buf + 1, sizeof(buf) - 1);
	StringCchCat(buf, MAX_PATH, "\"");
	StringCchPrintf(buf + lstrlen(buf), MAX_PATH - lstrlen(buf), " /BURN=%c,\"%s\",%d", param->cdletter, param->playlist_file, param->callback_hwnd);
	return (CreateProcess(NULL, buf, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) ? pi.dwProcessId : 0;
}
extern "C"
{
	typedef int (*BurnFunction)(const wchar_t*, HWND, DWORD, DWORD, DWORD , const wchar_t*);
}

#define BURNER_OK				0x0000
#define BURNER_FAILED			0x0001
#define BURNER_PRIMOFAILED		0x0FF0
#define BURNER_BADPLAYLISTPATH	0x0FF1
#define BURNER_BADTEMPPATH		0x0FF2
#define BURNER_BADCONFIGPATH	0x0FF3
#define BURNER_BADCOMMANDLINE	0x0FF4
#define BURNER_BADDRIVELETTER	0x0FF5
#define BURNER_EMPTYPLAYLIST	0x0FF6
#define BURNER_DIALOGFAILED		0x0FF7

void ReportError(HWND ownerWnd, int errorCode)
{
	wchar_t description[128] = {0};

	switch (errorCode)
	{
	case BURNER_OK: return ;
	case BURNER_PRIMOFAILED: getStringW(IDS_BURN_LIBRARY_INIT_FAILED,description,128); break;
	case BURNER_BADPLAYLISTPATH: getStringW(IDS_BURN_INVALID_PLAYLIST_PATH,description,128); break;
	case BURNER_BADTEMPPATH: getStringW(IDS_BURN_INVALID_TEMP_PATH,description,128); break;
	case BURNER_BADCONFIGPATH: getStringW(IDS_BURN_INVALID_CONFIG_PATH,description,128); break;
	case BURNER_BADCOMMANDLINE: getStringW(IDS_BURN_INVALID_CMDLINE,description,128); break;
	case BURNER_BADDRIVELETTER: getStringW(IDS_BURN_BAD_DRIVE_LETTER,description,128); break;
	case BURNER_EMPTYPLAYLIST: getStringW(IDS_BURN_LOAD_FROM_PLAYLIST_FAIL,description,128); break;
	case BURNER_DIALOGFAILED: getStringW(IDS_BURN_CREATE_DIALOG_FAIL,description,128); break;
	default: getStringW(IDS_BURN_UNKNOWN_ERROR,description,128); break;
	}

	wchar_t message[1024] = {0};
	if (S_OK != StringCchPrintfW(message, 1024, getStringW(IDS_BURN_INIT_ERROR_REASON,NULL,0), description))
	{
		StringCchCopyW(message, 1024, getStringW(IDS_BURN_INIT_ERROR_UNKNOWN,NULL,0));
	}
	MessageBoxW(ownerWnd, message, getStringW(IDS_BURN_NULLSOFT_STR,NULL,0), MB_OK | MB_ICONSTOP);
}

unsigned int burn_doBurn(char *cmdline, HWND winampWnd, HINSTANCE winampInstance)
{
//	PrimoSDK::Trace(FALSE);

#ifdef _DEBUG
	MessageBox(NULL, "Starting burner", "Debug", MB_OK);
#endif

	HWND	callbackWnd = 0;
	DWORD	speed = 0;
	DWORD	cdrom = 0;
	DWORD	flags = PRIMOSDK_CLOSEDISC;
	DWORD	errorCode = BURNER_OK;
	wchar_t	tmppath[4*MAX_PATH] = {0};
	wchar_t	in_wm[MAX_PATH] = {0};
	wchar_t	playlist[4096] = {0};

	// get temp path
	if (BURNER_OK == errorCode && !GetTempPathW(MAX_PATH, tmppath)) errorCode = BURNER_BADTEMPPATH;

	if (BURNER_OK == errorCode) //// parse parameters
	{
		if (lstrlenA(cmdline) < 1) errorCode = BURNER_BADCOMMANDLINE;

		if (BURNER_OK == errorCode)
		{
			// drive letter
			CharUpperBuff(cmdline, 1);
			cdrom = cmdline[0];
			for (int i = 0; i < 2; i++) cmdline = CharNext(cmdline);
			if (cdrom < 'A' || cdrom > 'Z') errorCode = BURNER_BADDRIVELETTER;
		}

		if (BURNER_OK == errorCode)
		{
			// callback window
			char *current = cmdline + lstrlenA(cmdline);
			while (current != cmdline && *current != ',') current = CharPrevA(cmdline, current);
			callbackWnd = (current != cmdline) ? (HWND)atoi(CharNext(current)) : NULL;

			// playlist path
			size_t cchLen = current - cmdline;
			if (cchLen == 0) errorCode = BURNER_BADPLAYLISTPATH;

			if (BURNER_OK == errorCode)
			{
				if (!MultiByteToWideCharSZ(CP_ACP, 0, cmdline, current - cmdline, playlist, 4096)) errorCode = BURNER_BADPLAYLISTPATH;
				else playlist[cchLen] = 0x0000;
			}
		}

		if (BURNER_OK == errorCode)
		{
			speed = GetPrivateProfileIntW(L"gen_ml_config", L"cdburnspeed", PRIMOSDK_MIN, ML_INI_FILE);
			DWORD maxspeed = GetPrivateProfileIntW(L"gen_ml_config", L"cdburnmaxspeed", PRIMOSDK_MIN, ML_INI_FILE);
			if (!getRegVer(winampWnd)) speed = PRIMOSDK_MIN;
			if (!speed) speed = maxspeed;
			if (!speed) speed = PRIMOSDK_MIN;

			flags |= (GetPrivateProfileIntW(L"gen_ml_config", L"cdburntestmode", 0, ML_INI_FILE)) ? PRIMOSDK_TEST : PRIMOSDK_WRITE;
			flags |= (GetPrivateProfileIntW(L"gen_ml_config", L"cdburnproof", 0, ML_INI_FILE)) ? PRIMOSDK_BURNPROOF : 0;
		}
	}

	if (BURNER_OK != errorCode)
	{
		if (playlist[0] != 0x0000) DeleteFileW(playlist);
		ReportError(callbackWnd, errorCode);
		return errorCode;
	}

	// try in_wm version first
	PathCombineW(in_wm, PLUGINDIR, L"in_wm.dll");
	BurnFunction burnFunc = NULL;
	HMODULE lib = LoadLibraryW(in_wm);
	if (lib)
	{
		burnFunc = (BurnFunction)GetProcAddress(lib, "burn_doBurn");
		if (burnFunc)
		{
			errorCode = burnFunc(playlist, callbackWnd, cdrom, speed, flags, tmppath);
		}
	}
	if (lib) FreeLibrary(lib);
	lib = NULL;

	if (!burnFunc)
	{
		InitializeBurningLibrary(WASABI_API_SVC, hMainInstance, winampWnd);
		BurnerPlaylist burnPL;
		burnPL.Load(playlist);
		if (!burnPL.GetCount()) errorCode = BURNER_EMPTYPLAYLIST;
		else
		{
			obj_primo *primo=0;
			waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(obj_primo::getServiceGuid());
			if (sf) primo = reinterpret_cast<obj_primo *>(sf->getInterface());
			if (!primo)
				errorCode = BURNER_PRIMOFAILED;
			else
			{
				BurnPlaylistUI burnDlg;
				errorCode = burnDlg.Burn(primo, cdrom, speed, flags, &burnPL, tmppath, callbackWnd);
				sf->releaseInterface(primo);
			}
		}
	}

	DeleteFileW(playlist);
	if (BURNER_OK != errorCode) ReportError(callbackWnd, errorCode);
	return errorCode;
}
#endif