1 /*
2 LICENSE
3 -------
4 Copyright 2005-2013 Nullsoft, Inc.
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without modification,
8 are permitted provided that the following conditions are met:
9
10 * Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12
13 * Redistributions in binary form must reproduce the above copyright notice,
14 this list of conditions and the following disclaimer in the documentation
15 and/or other materials provided with the distribution.
16
17 * Neither the name of Nullsoft nor the names of its contributors may be used to
18 endorse or promote products derived from this software without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
21 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
27 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include "api.h"
31 #include "utility.h"
32 #include <math.h>
33 #include <locale.h>
34 #include <windows.h>
35 #ifdef _DEBUG
36 #define D3D_DEBUG_INFO // declare this before including d3d9.h
37 #endif
38 #include <d3d9.h>
39 #include "../Winamp/wa_ipc.h"
40 #include "resource.h"
41 #include <shellapi.h>
42
myOpenURL(HWND hwnd,wchar_t * loc)43 intptr_t myOpenURL(HWND hwnd, wchar_t *loc)
44 {
45 if (loc)
46 {
47 bool override=false;
48 WASABI_API_SYSCB->syscb_issueCallback(SysCallback::BROWSER, BrowserCallback::ONOPENURL, reinterpret_cast<intptr_t>(loc), reinterpret_cast<intptr_t>(&override));
49 if (!override)
50 return (intptr_t)ShellExecuteW(hwnd, L"open", loc, NULL, NULL, SW_SHOWNORMAL);
51 else
52 return 33;
53 }
54 return 33;
55 }
56
PowCosineInterp(float x,float pow)57 float PowCosineInterp(float x, float pow)
58 {
59 // input (x) & output should be in range 0..1.
60 // pow > 0: tends to push things toward 0 and 1
61 // pow < 0: tends to push things toward 0.5.
62
63 if (x<0)
64 return 0;
65 if (x>1)
66 return 1;
67
68 int bneg = (pow < 0) ? 1 : 0;
69 if (bneg)
70 pow = -pow;
71
72 if (pow>1000) pow=1000;
73
74 int its = (int)pow;
75 for (int i=0; i<its; i++)
76 {
77 if (bneg)
78 x = InvCosineInterp(x);
79 else
80 x = CosineInterp(x);
81 }
82 float x2 = (bneg) ? InvCosineInterp(x) : CosineInterp(x);
83 float dx = pow - its;
84 return ((1-dx)*x + (dx)*x2);
85 }
86
AdjustRateToFPS(float per_frame_decay_rate_at_fps1,float fps1,float actual_fps)87 float AdjustRateToFPS(float per_frame_decay_rate_at_fps1, float fps1, float actual_fps)
88 {
89 // returns the equivalent per-frame decay rate at actual_fps
90
91 // basically, do all your testing at fps1 and get a good decay rate;
92 // then, in the real application, adjust that rate by the actual fps each time you use it.
93
94 float per_second_decay_rate_at_fps1 = powf(per_frame_decay_rate_at_fps1, fps1);
95 float per_frame_decay_rate_at_fps2 = powf(per_second_decay_rate_at_fps1, 1.0f/actual_fps);
96
97 return per_frame_decay_rate_at_fps2;
98 }
99
GetPrivateProfileFloatW(wchar_t * szSectionName,wchar_t * szKeyName,float fDefault,wchar_t * szIniFile)100 float GetPrivateProfileFloatW(wchar_t *szSectionName, wchar_t *szKeyName, float fDefault, wchar_t *szIniFile)
101 {
102 wchar_t string[64];
103 wchar_t szDefault[64];
104 float ret = fDefault;
105
106 _swprintf_l(szDefault, L"%f", g_use_C_locale, fDefault);
107
108 if (GetPrivateProfileStringW(szSectionName, szKeyName, szDefault, string, 64, szIniFile) > 0)
109 {
110 _swscanf_l(string, L"%f", g_use_C_locale, &ret);
111 }
112 return ret;
113 }
114
WritePrivateProfileFloatW(float f,wchar_t * szKeyName,wchar_t * szIniFile,wchar_t * szSectionName)115 bool WritePrivateProfileFloatW(float f, wchar_t *szKeyName, wchar_t *szIniFile, wchar_t *szSectionName)
116 {
117 wchar_t szValue[32];
118 _swprintf_l(szValue, L"%f", g_use_C_locale, f);
119 return (WritePrivateProfileStringW(szSectionName, szKeyName, szValue, szIniFile) != 0);
120 }
121
WritePrivateProfileIntW(int d,wchar_t * szKeyName,wchar_t * szIniFile,wchar_t * szSectionName)122 bool WritePrivateProfileIntW(int d, wchar_t *szKeyName, wchar_t *szIniFile, wchar_t *szSectionName)
123 {
124 wchar_t szValue[32];
125 swprintf(szValue, L"%d", d);
126 return (WritePrivateProfileStringW(szSectionName, szKeyName, szValue, szIniFile) != 0);
127 }
128
SetScrollLock(int bNewState,bool bPreventHandling)129 void SetScrollLock(int bNewState, bool bPreventHandling)
130 {
131 if(bPreventHandling) return;
132
133 if (bNewState != (GetKeyState(VK_SCROLL) & 1))
134 {
135 // Simulate a key press
136 keybd_event( VK_SCROLL,
137 0x45,
138 KEYEVENTF_EXTENDEDKEY | 0,
139 0 );
140
141 // Simulate a key release
142 keybd_event( VK_SCROLL,
143 0x45,
144 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,
145 0);
146 }
147 }
148
RemoveExtension(wchar_t * str)149 void RemoveExtension(wchar_t *str)
150 {
151 wchar_t *p = wcsrchr(str, L'.');
152 if (p) *p = 0;
153 }
154
ShiftDown(wchar_t * str)155 static void ShiftDown(wchar_t *str)
156 {
157 while (*str)
158 {
159 str[0] = str[1];
160 str++;
161 }
162 }
163
RemoveSingleAmpersands(wchar_t * str)164 void RemoveSingleAmpersands(wchar_t *str)
165 {
166 while (*str)
167 {
168 if (str[0] == L'&')
169 {
170 if (str[1] == L'&') // two in a row: replace with single ampersand, move on
171 str++;
172
173 ShiftDown(str);
174 }
175 else
176 str = CharNextW(str);
177 }
178 }
179
TextToGuid(char * str,GUID * pGUID)180 void TextToGuid(char *str, GUID *pGUID)
181 {
182 if (!str) return;
183 if (!pGUID) return;
184
185 DWORD d[11];
186
187 sscanf(str, "%X %X %X %X %X %X %X %X %X %X %X",
188 &d[0], &d[1], &d[2], &d[3], &d[4], &d[5], &d[6], &d[7], &d[8], &d[9], &d[10]);
189
190 pGUID->Data1 = (DWORD)d[0];
191 pGUID->Data2 = (WORD)d[1];
192 pGUID->Data3 = (WORD)d[2];
193 pGUID->Data4[0] = (BYTE)d[3];
194 pGUID->Data4[1] = (BYTE)d[4];
195 pGUID->Data4[2] = (BYTE)d[5];
196 pGUID->Data4[3] = (BYTE)d[6];
197 pGUID->Data4[4] = (BYTE)d[7];
198 pGUID->Data4[5] = (BYTE)d[8];
199 pGUID->Data4[6] = (BYTE)d[9];
200 pGUID->Data4[7] = (BYTE)d[10];
201 }
202
GuidToText(GUID * pGUID,char * str,int nStrLen)203 void GuidToText(GUID *pGUID, char *str, int nStrLen)
204 {
205 // note: nStrLen should be set to sizeof(str).
206 if (!str) return;
207 if (!nStrLen) return;
208 str[0] = 0;
209 if (!pGUID) return;
210
211 DWORD d[11];
212 d[0] = (DWORD)pGUID->Data1;
213 d[1] = (DWORD)pGUID->Data2;
214 d[2] = (DWORD)pGUID->Data3;
215 d[3] = (DWORD)pGUID->Data4[0];
216 d[4] = (DWORD)pGUID->Data4[1];
217 d[5] = (DWORD)pGUID->Data4[2];
218 d[6] = (DWORD)pGUID->Data4[3];
219 d[7] = (DWORD)pGUID->Data4[4];
220 d[8] = (DWORD)pGUID->Data4[5];
221 d[9] = (DWORD)pGUID->Data4[6];
222 d[10] = (DWORD)pGUID->Data4[7];
223
224 sprintf(str, "%08X %04X %04X %02X %02X %02X %02X %02X %02X %02X %02X",
225 d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10]);
226 }
227
228 /*
229 int GetPentiumTimeRaw(unsigned __int64 *cpu_timestamp)
230 {
231 // returns 0 on failure, 1 on success
232 // warning: watch out for wraparound!
233
234 // note: it's probably better to use QueryPerformanceFrequency
235 // and QueryPerformanceCounter()!
236
237 // get high-precision time:
238 __try
239 {
240 unsigned __int64 *dest = (unsigned __int64 *)cpu_timestamp;
241 __asm
242 {
243 _emit 0xf // these two bytes form the 'rdtsc' asm instruction,
244 _emit 0x31 // available on Pentium I and later.
245 mov esi, dest
246 mov [esi ], eax // lower 32 bits of tsc
247 mov [esi+4], edx // upper 32 bits of tsc
248 }
249 return 1;
250 }
251 __except(EXCEPTION_EXECUTE_HANDLER)
252 {
253 return 0;
254 }
255
256 return 0;
257 }
258
259 double GetPentiumTimeAsDouble(unsigned __int64 frequency)
260 {
261 // returns < 0 on failure; otherwise, returns current cpu time, in seconds.
262 // warning: watch out for wraparound!
263
264 // note: it's probably better to use QueryPerformanceFrequency
265 // and QueryPerformanceCounter()!
266
267 if (frequency==0)
268 return -1.0;
269
270 // get high-precision time:
271 __try
272 {
273 unsigned __int64 high_perf_time;
274 unsigned __int64 *dest = &high_perf_time;
275 __asm
276 {
277 _emit 0xf // these two bytes form the 'rdtsc' asm instruction,
278 _emit 0x31 // available on Pentium I and later.
279 mov esi, dest
280 mov [esi ], eax // lower 32 bits of tsc
281 mov [esi+4], edx // upper 32 bits of tsc
282 }
283 __int64 time_s = (__int64)(high_perf_time / frequency); // unsigned->sign conversion should be safe here
284 __int64 time_fract = (__int64)(high_perf_time % frequency); // unsigned->sign conversion should be safe here
285 // note: here, we wrap the timer more frequently (once per week)
286 // than it otherwise would (VERY RARELY - once every 585 years on
287 // a 1 GHz), to alleviate floating-point precision errors that start
288 // to occur when you get to very high counter values.
289 double ret = (time_s % (60*60*24*7)) + (double)time_fract/(double)((__int64)frequency);
290 return ret;
291 }
292 __except(EXCEPTION_EXECUTE_HANDLER)
293 {
294 return -1.0;
295 }
296
297 return -1.0;
298 }
299 */
300
301 #ifdef _DEBUG
OutputDebugMessage(char * szStartText,HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)302 void OutputDebugMessage(char *szStartText, HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
303 {
304 // note: this function does NOT log WM_MOUSEMOVE, WM_NCHITTEST, or WM_SETCURSOR
305 // messages, since they are so frequent.
306 // note: these identifiers were pulled from winuser.h
307
308 //if (msg == WM_MOUSEMOVE || msg == WM_NCHITTEST || msg == WM_SETCURSOR)
309 // return;
310
311 #ifdef _DEBUG
312 char buf[64];
313 int matched = 1;
314
315 sprintf(buf, "WM_");
316
317 switch(msg)
318 {
319 case 0x0001: lstrcat(buf, "CREATE"); break;
320 case 0x0002: lstrcat(buf, "DESTROY"); break;
321 case 0x0003: lstrcat(buf, "MOVE"); break;
322 case 0x0005: lstrcat(buf, "SIZE"); break;
323 case 0x0006: lstrcat(buf, "ACTIVATE"); break;
324 case 0x0007: lstrcat(buf, "SETFOCUS"); break;
325 case 0x0008: lstrcat(buf, "KILLFOCUS"); break;
326 case 0x000A: lstrcat(buf, "ENABLE"); break;
327 case 0x000B: lstrcat(buf, "SETREDRAW"); break;
328 case 0x000C: lstrcat(buf, "SETTEXT"); break;
329 case 0x000D: lstrcat(buf, "GETTEXT"); break;
330 case 0x000E: lstrcat(buf, "GETTEXTLENGTH"); break;
331 case 0x000F: lstrcat(buf, "PAINT"); break;
332 case 0x0010: lstrcat(buf, "CLOSE"); break;
333 case 0x0011: lstrcat(buf, "QUERYENDSESSION"); break;
334 case 0x0012: lstrcat(buf, "QUIT"); break;
335 case 0x0013: lstrcat(buf, "QUERYOPEN"); break;
336 case 0x0014: lstrcat(buf, "ERASEBKGND"); break;
337 case 0x0015: lstrcat(buf, "SYSCOLORCHANGE"); break;
338 case 0x0016: lstrcat(buf, "ENDSESSION"); break;
339 case 0x0018: lstrcat(buf, "SHOWWINDOW"); break;
340 case 0x001A: lstrcat(buf, "WININICHANGE"); break;
341 case 0x001B: lstrcat(buf, "DEVMODECHANGE"); break;
342 case 0x001C: lstrcat(buf, "ACTIVATEAPP"); break;
343 case 0x001D: lstrcat(buf, "FONTCHANGE"); break;
344 case 0x001E: lstrcat(buf, "TIMECHANGE"); break;
345 case 0x001F: lstrcat(buf, "CANCELMODE"); break;
346 case 0x0020: lstrcat(buf, "SETCURSOR"); break;
347 case 0x0021: lstrcat(buf, "MOUSEACTIVATE"); break;
348 case 0x0022: lstrcat(buf, "CHILDACTIVATE"); break;
349 case 0x0023: lstrcat(buf, "QUEUESYNC"); break;
350 case 0x0024: lstrcat(buf, "GETMINMAXINFO"); break;
351 case 0x0026: lstrcat(buf, "PAINTICON"); break;
352 case 0x0027: lstrcat(buf, "ICONERASEBKGND"); break;
353 case 0x0028: lstrcat(buf, "NEXTDLGCTL"); break;
354 case 0x002A: lstrcat(buf, "SPOOLERSTATUS"); break;
355 case 0x002B: lstrcat(buf, "DRAWITEM"); break;
356 case 0x002C: lstrcat(buf, "MEASUREITEM"); break;
357 case 0x002D: lstrcat(buf, "DELETEITEM"); break;
358 case 0x002E: lstrcat(buf, "VKEYTOITEM"); break;
359 case 0x002F: lstrcat(buf, "CHARTOITEM"); break;
360 case 0x0030: lstrcat(buf, "SETFONT"); break;
361 case 0x0031: lstrcat(buf, "GETFONT"); break;
362 case 0x0032: lstrcat(buf, "SETHOTKEY"); break;
363 case 0x0033: lstrcat(buf, "GETHOTKEY"); break;
364 case 0x0037: lstrcat(buf, "QUERYDRAGICON"); break;
365 case 0x0039: lstrcat(buf, "COMPAREITEM"); break;
366 case 0x0041: lstrcat(buf, "COMPACTING"); break;
367 case 0x0044: lstrcat(buf, "COMMNOTIFY"); break;
368 case 0x0046: lstrcat(buf, "WINDOWPOSCHANGING"); break;
369 case 0x0047: lstrcat(buf, "WINDOWPOSCHANGED"); break;
370 case 0x0048: lstrcat(buf, "POWER"); break;
371 case 0x004A: lstrcat(buf, "COPYDATA"); break;
372 case 0x004B: lstrcat(buf, "CANCELJOURNAL"); break;
373
374 #if(WINVER >= 0x0400)
375 case 0x004E: lstrcat(buf, "NOTIFY"); break;
376 case 0x0050: lstrcat(buf, "INPUTLANGCHANGEREQUEST"); break;
377 case 0x0051: lstrcat(buf, "INPUTLANGCHANGE"); break;
378 case 0x0052: lstrcat(buf, "TCARD"); break;
379 case 0x0053: lstrcat(buf, "HELP"); break;
380 case 0x0054: lstrcat(buf, "USERCHANGED"); break;
381 case 0x0055: lstrcat(buf, "NOTIFYFORMAT"); break;
382 case 0x007B: lstrcat(buf, "CONTEXTMENU"); break;
383 case 0x007C: lstrcat(buf, "STYLECHANGING"); break;
384 case 0x007D: lstrcat(buf, "STYLECHANGED"); break;
385 case 0x007E: lstrcat(buf, "DISPLAYCHANGE"); break;
386 case 0x007F: lstrcat(buf, "GETICON"); break;
387 case 0x0080: lstrcat(buf, "SETICON"); break;
388 #endif
389
390 case 0x0081: lstrcat(buf, "NCCREATE"); break;
391 case 0x0082: lstrcat(buf, "NCDESTROY"); break;
392 case 0x0083: lstrcat(buf, "NCCALCSIZE"); break;
393 case 0x0084: lstrcat(buf, "NCHITTEST"); break;
394 case 0x0085: lstrcat(buf, "NCPAINT"); break;
395 case 0x0086: lstrcat(buf, "NCACTIVATE"); break;
396 case 0x0087: lstrcat(buf, "GETDLGCODE"); break;
397 case 0x0088: lstrcat(buf, "SYNCPAINT"); break;
398 case 0x00A0: lstrcat(buf, "NCMOUSEMOVE"); break;
399 case 0x00A1: lstrcat(buf, "NCLBUTTONDOWN"); break;
400 case 0x00A2: lstrcat(buf, "NCLBUTTONUP"); break;
401 case 0x00A3: lstrcat(buf, "NCLBUTTONDBLCLK"); break;
402 case 0x00A4: lstrcat(buf, "NCRBUTTONDOWN"); break;
403 case 0x00A5: lstrcat(buf, "NCRBUTTONUP"); break;
404 case 0x00A6: lstrcat(buf, "NCRBUTTONDBLCLK"); break;
405 case 0x00A7: lstrcat(buf, "NCMBUTTONDOWN"); break;
406 case 0x00A8: lstrcat(buf, "NCMBUTTONUP"); break;
407 case 0x00A9: lstrcat(buf, "NCMBUTTONDBLCLK"); break;
408 case 0x0100: lstrcat(buf, "KEYDOWN"); break;
409 case 0x0101: lstrcat(buf, "KEYUP"); break;
410 case 0x0102: lstrcat(buf, "CHAR"); break;
411 case 0x0103: lstrcat(buf, "DEADCHAR"); break;
412 case 0x0104: lstrcat(buf, "SYSKEYDOWN"); break;
413 case 0x0105: lstrcat(buf, "SYSKEYUP"); break;
414 case 0x0106: lstrcat(buf, "SYSCHAR"); break;
415 case 0x0107: lstrcat(buf, "SYSDEADCHAR"); break;
416 case 0x0108: lstrcat(buf, "KEYLAST"); break;
417
418 #if(WINVER >= 0x0400)
419 case 0x010D: lstrcat(buf, "IME_STARTCOMPOSITION"); break;
420 case 0x010E: lstrcat(buf, "IME_ENDCOMPOSITION"); break;
421 case 0x010F: lstrcat(buf, "IME_COMPOSITION"); break;
422 //case 0x010F: lstrcat(buf, "IME_KEYLAST"); break;
423 #endif
424
425 case 0x0110: lstrcat(buf, "INITDIALOG"); break;
426 case 0x0111: lstrcat(buf, "COMMAND"); break;
427 case 0x0112: lstrcat(buf, "SYSCOMMAND"); break;
428 case 0x0113: lstrcat(buf, "TIMER"); break;
429 case 0x0114: lstrcat(buf, "HSCROLL"); break;
430 case 0x0115: lstrcat(buf, "VSCROLL"); break;
431 case 0x0116: lstrcat(buf, "INITMENU"); break;
432 case 0x0117: lstrcat(buf, "INITMENUPOPUP"); break;
433 case 0x011F: lstrcat(buf, "MENUSELECT"); break;
434 case 0x0120: lstrcat(buf, "MENUCHAR"); break;
435 case 0x0121: lstrcat(buf, "ENTERIDLE"); break;
436 #if(WINVER >= 0x0500)
437 case 0x0122: lstrcat(buf, "MENURBUTTONUP"); break;
438 case 0x0123: lstrcat(buf, "MENUDRAG"); break;
439 case 0x0124: lstrcat(buf, "MENUGETOBJECT"); break;
440 case 0x0125: lstrcat(buf, "UNINITMENUPOPUP"); break;
441 case 0x0126: lstrcat(buf, "MENUCOMMAND"); break;
442 #endif
443
444 case 0x0132: lstrcat(buf, "CTLCOLORMSGBOX"); break;
445 case 0x0133: lstrcat(buf, "CTLCOLOREDIT"); break;
446 case 0x0134: lstrcat(buf, "CTLCOLORLISTBOX"); break;
447 case 0x0135: lstrcat(buf, "CTLCOLORBTN"); break;
448 case 0x0136: lstrcat(buf, "CTLCOLORDLG"); break;
449 case 0x0137: lstrcat(buf, "CTLCOLORSCROLLBAR"); break;
450 case 0x0138: lstrcat(buf, "CTLCOLORSTATIC"); break;
451
452 //case 0x0200: lstrcat(buf, "MOUSEFIRST"); break;
453 case 0x0200: lstrcat(buf, "MOUSEMOVE"); break;
454 case 0x0201: lstrcat(buf, "LBUTTONDOWN"); break;
455 case 0x0202: lstrcat(buf, "LBUTTONUP"); break;
456 case 0x0203: lstrcat(buf, "LBUTTONDBLCLK"); break;
457 case 0x0204: lstrcat(buf, "RBUTTONDOWN"); break;
458 case 0x0205: lstrcat(buf, "RBUTTONUP"); break;
459 case 0x0206: lstrcat(buf, "RBUTTONDBLCLK"); break;
460 case 0x0207: lstrcat(buf, "MBUTTONDOWN"); break;
461 case 0x0208: lstrcat(buf, "MBUTTONUP"); break;
462 case 0x0209: lstrcat(buf, "MBUTTONDBLCLK"); break;
463
464 #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
465 case 0x020A: lstrcat(buf, "MOUSEWHEEL"); break;
466 case 0x020E: lstrcat(buf, "MOUSELAST"); break;
467 #else
468 //case 0x0209: lstrcat(buf, "MOUSELAST"); break;
469 #endif
470
471 case 0x0210: lstrcat(buf, "PARENTNOTIFY"); break;
472 case 0x0211: lstrcat(buf, "ENTERMENULOOP"); break;
473 case 0x0212: lstrcat(buf, "EXITMENULOOP"); break;
474
475 #if(WINVER >= 0x0400)
476 case 0x0213: lstrcat(buf, "NEXTMENU"); break;
477 case 0x0214: lstrcat(buf, "SIZING"); break;
478 case 0x0215: lstrcat(buf, "CAPTURECHANGED"); break;
479 case 0x0216: lstrcat(buf, "MOVING"); break;
480 case 0x0218: lstrcat(buf, "POWERBROADCAST"); break;
481 case 0x0219: lstrcat(buf, "DEVICECHANGE"); break;
482 #endif
483
484 /*
485 case 0x0220: lstrcat(buf, "MDICREATE"); break;
486 case 0x0221: lstrcat(buf, "MDIDESTROY"); break;
487 case 0x0222: lstrcat(buf, "MDIACTIVATE"); break;
488 case 0x0223: lstrcat(buf, "MDIRESTORE"); break;
489 case 0x0224: lstrcat(buf, "MDINEXT"); break;
490 case 0x0225: lstrcat(buf, "MDIMAXIMIZE"); break;
491 case 0x0226: lstrcat(buf, "MDITILE"); break;
492 case 0x0227: lstrcat(buf, "MDICASCADE"); break;
493 case 0x0228: lstrcat(buf, "MDIICONARRANGE"); break;
494 case 0x0229: lstrcat(buf, "MDIGETACTIVE"); break;
495 */
496
497 case 0x0230: lstrcat(buf, "MDISETMENU"); break;
498 case 0x0231: lstrcat(buf, "ENTERSIZEMOVE"); break;
499 case 0x0232: lstrcat(buf, "EXITSIZEMOVE"); break;
500 case 0x0233: lstrcat(buf, "DROPFILES"); break;
501 case 0x0234: lstrcat(buf, "MDIREFRESHMENU"); break;
502
503
504 /*
505 #if(WINVER >= 0x0400)
506 case 0x0281: lstrcat(buf, "IME_SETCONTEXT"); break;
507 case 0x0282: lstrcat(buf, "IME_NOTIFY"); break;
508 case 0x0283: lstrcat(buf, "IME_CONTROL"); break;
509 case 0x0284: lstrcat(buf, "IME_COMPOSITIONFULL"); break;
510 case 0x0285: lstrcat(buf, "IME_SELECT"); break;
511 case 0x0286: lstrcat(buf, "IME_CHAR"); break;
512 #endif
513 #if(WINVER >= 0x0500)
514 case 0x0288: lstrcat(buf, "IME_REQUEST"); break;
515 #endif
516 #if(WINVER >= 0x0400)
517 case 0x0290: lstrcat(buf, "IME_KEYDOWN"); break;
518 case 0x0291: lstrcat(buf, "IME_KEYUP"); break;
519 #endif
520 */
521
522 #if(_WIN32_WINNT >= 0x0400)
523 case 0x02A1: lstrcat(buf, "MOUSEHOVER"); break;
524 case 0x02A3: lstrcat(buf, "MOUSELEAVE"); break;
525 #endif
526
527 case 0x0300: lstrcat(buf, "CUT"); break;
528 case 0x0301: lstrcat(buf, "COPY"); break;
529 case 0x0302: lstrcat(buf, "PASTE"); break;
530 case 0x0303: lstrcat(buf, "CLEAR"); break;
531 case 0x0304: lstrcat(buf, "UNDO"); break;
532 case 0x0305: lstrcat(buf, "RENDERFORMAT"); break;
533 case 0x0306: lstrcat(buf, "RENDERALLFORMATS"); break;
534 case 0x0307: lstrcat(buf, "DESTROYCLIPBOARD"); break;
535 case 0x0308: lstrcat(buf, "DRAWCLIPBOARD"); break;
536 case 0x0309: lstrcat(buf, "PAINTCLIPBOARD"); break;
537 case 0x030A: lstrcat(buf, "VSCROLLCLIPBOARD"); break;
538 case 0x030B: lstrcat(buf, "SIZECLIPBOARD"); break;
539 case 0x030C: lstrcat(buf, "ASKCBFORMATNAME"); break;
540 case 0x030D: lstrcat(buf, "CHANGECBCHAIN"); break;
541 case 0x030E: lstrcat(buf, "HSCROLLCLIPBOARD"); break;
542 case 0x030F: lstrcat(buf, "QUERYNEWPALETTE"); break;
543 case 0x0310: lstrcat(buf, "PALETTEISCHANGING"); break;
544 case 0x0311: lstrcat(buf, "PALETTECHANGED"); break;
545 case 0x0312: lstrcat(buf, "HOTKEY"); break;
546
547 #if(WINVER >= 0x0400)
548 case 0x0317: lstrcat(buf, "PRINT"); break;
549 case 0x0318: lstrcat(buf, "PRINTCLIENT"); break;
550
551 case 0x0358: lstrcat(buf, "HANDHELDFIRST"); break;
552 case 0x035F: lstrcat(buf, "HANDHELDLAST"); break;
553
554 case 0x0360: lstrcat(buf, "AFXFIRST"); break;
555 case 0x037F: lstrcat(buf, "AFXLAST"); break;
556 #endif
557
558 case 0x0380: lstrcat(buf, "PENWINFIRST"); break;
559 case 0x038F: lstrcat(buf, "PENWINLAST"); break;
560
561 default:
562 sprintf(buf, "unknown");
563 matched = 0;
564 break;
565 }
566
567 int n = strlen(buf);
568 int desired_len = 24;
569 int spaces_to_append = desired_len-n;
570 if (spaces_to_append>0)
571 {
572 for (int i=0; i<spaces_to_append; i++)
573 buf[n+i] = ' ';
574 buf[desired_len] = 0;
575 }
576
577 char buf2[256];
578 if (matched)
579 sprintf(buf2, "%shwnd=%08x, msg=%s, w=%08x, l=%08x\n", szStartText, hwnd, buf, wParam, lParam);
580 else
581 sprintf(buf2, "%shwnd=%08x, msg=unknown/0x%08x, w=%08x, l=%08x\n", szStartText, hwnd, msg, wParam, lParam);
582 OutputDebugString(buf2);
583 #endif
584 }
585 #endif
586
DownloadDirectX(HWND hwnd)587 void DownloadDirectX(HWND hwnd)
588 {
589 wchar_t szUrl[] = L"http://www.microsoft.com/download/details.aspx?id=35";
590 intptr_t ret = myOpenURL(NULL, szUrl);
591 if (ret <= 32)
592 {
593 wchar_t buf[1024];
594 switch(ret)
595 {
596 case SE_ERR_FNF:
597 case SE_ERR_PNF:
598 swprintf(buf, WASABI_API_LNGSTRINGW(IDS_URL_COULD_NOT_OPEN), szUrl);
599 break;
600 case SE_ERR_ACCESSDENIED:
601 case SE_ERR_SHARE:
602 swprintf(buf, WASABI_API_LNGSTRINGW(IDS_ACCESS_TO_URL_WAS_DENIED), szUrl);
603 break;
604 case SE_ERR_NOASSOC:
605 swprintf(buf, WASABI_API_LNGSTRINGW(IDS_ACCESS_TO_URL_FAILED_DUE_TO_NO_ASSOC), szUrl);
606 break;
607 default:
608 swprintf(buf, WASABI_API_LNGSTRINGW(IDS_ACCESS_TO_URL_FAILED_CODE_X), szUrl, ret);
609 break;
610 }
611 MessageBoxW(hwnd, buf, WASABI_API_LNGSTRINGW(IDS_ERROR_OPENING_URL),
612 MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL);
613 }
614 }
615
MissingDirectX(HWND hwnd)616 void MissingDirectX(HWND hwnd)
617 {
618 // DIRECTX MISSING OR CORRUPT -> PROMPT TO GO TO WEB.
619 wchar_t title[128];
620 int ret = MessageBoxW(hwnd,
621 #ifndef D3D_SDK_VERSION
622 --- error; you need to #include <d3d9.h> ---
623 #endif
624 #if (D3D_SDK_VERSION==120)
625 // plugin was *built* using the DirectX 9.0 sdk, therefore,
626 // the dx9.0 runtime is missing or corrupt
627 "Failed to initialize DirectX 9.0 or later.\n"
628 "Milkdrop requires d3dx9_31.dll to be installed.\n"
629 "\n"
630 "Would you like to be taken to:\n"
631 "http://www.microsoft.com/download/details.aspx?id=35,\n"
632 "where you can update DirectX 9.0?\n"
633 XXXXXXX
634 #else
635 // plugin was *built* using some other version of the DirectX9 sdk, such as
636 // 9.1b; therefore, we don't know exactly what version to tell them they need
637 // to install; so we ask them to go get the *latest* version.
638 WASABI_API_LNGSTRINGW(IDS_DIRECTX_MISSING_OR_CORRUPT_TEXT)
639 #endif
640 ,
641 WASABI_API_LNGSTRINGW_BUF(IDS_DIRECTX_MISSING_OR_CORRUPT, title, 128),
642 MB_YESNO|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL);
643
644 if (ret==IDYES)
645 DownloadDirectX(hwnd);
646 }
647
CheckForMMX()648 bool CheckForMMX()
649 {
650 DWORD bMMX = 0;
651 DWORD *pbMMX = &bMMX;
652 __try {
653 __asm {
654 mov eax, 1
655 cpuid
656 mov edi, pbMMX
657 mov dword ptr [edi], edx
658 }
659 }
660 __except(EXCEPTION_EXECUTE_HANDLER)
661 {
662 bMMX = 0;
663 }
664
665 if (bMMX & 0x00800000) // check bit 23
666 return true;
667
668 return false;
669 }
670
CheckForSSE()671 bool CheckForSSE()
672 {
673 #ifdef _WIN64
674 return true; // All x64 processors support SSE
675 #else
676 /*
677 The SSE instruction set was introduced with the Pentium III and features:
678 * Additional MMX instructions such as min/max
679 * Prefetch and write-through instructions for optimizing data movement
680 from and to the L2/L3 caches and main memory
681 * 8 New 128 bit XMM registers (xmm0..xmm7) and corresponding 32 bit floating point
682 (single precision) instructions
683 */
684
685 DWORD bSSE = 0;
686 DWORD *pbSSE = &bSSE;
687 __try {
688 __asm
689 {
690 mov eax, 1
691 cpuid
692 mov edi, pbSSE
693 mov dword ptr [edi], edx
694 }
695 }
696 __except(EXCEPTION_EXECUTE_HANDLER)
697 {
698 bSSE = 0;
699 }
700
701 if (bSSE & 0x02000000) // check bit 25
702 return true;
703
704 return false;
705 #endif
706 }
707
GetDesktopFolder(char * szDesktopFolder)708 void GetDesktopFolder(char *szDesktopFolder) // should be MAX_PATH len.
709 {
710 // returns the path to the desktop folder, WITHOUT a trailing backslash.
711 szDesktopFolder[0] = 0;
712 ITEMIDLIST pidl;
713 ZeroMemory(&pidl, sizeof(pidl));
714 if (!SHGetPathFromIDList(&pidl, szDesktopFolder))
715 szDesktopFolder[0] = 0;
716 }
717
ExecutePidl(LPITEMIDLIST pidl,char * szPathAndFile,char * szWorkingDirectory,HWND hWnd)718 void ExecutePidl(LPITEMIDLIST pidl, char *szPathAndFile, char *szWorkingDirectory, HWND hWnd)
719 {
720 // This function was based on code by Jeff Prosise.
721
722 // Note: for some reason, ShellExecuteEx fails when executing
723 // *shortcuts* (.lnk files) from the desktop, using their PIDLs.
724 // So, if that fails, we try again w/the plain old text filename
725 // (szPathAndFile).
726
727 char szVerb[] = "open";
728 char szFilename2[MAX_PATH];
729
730 sprintf(szFilename2, "%s.lnk", szPathAndFile);
731
732 // -without the "no-verb" pass,
733 // certain icons still don't work (like shortcuts
734 // to IE, VTune...)
735 // -without the "context menu" pass,
736 // certain others STILL don't work (Netscape...)
737 // -without the 'ntry' pass, shortcuts (to folders/files)
738 // don't work
739 for (int verb_pass=0; verb_pass<2; verb_pass++)
740 {
741 for (int ntry=0; ntry<3; ntry++)
742 {
743 for (int context_pass=0; context_pass<2; context_pass++)
744 {
745 SHELLEXECUTEINFO sei = { sizeof(sei) };
746 sei.hwnd = hWnd;
747 sei.fMask = SEE_MASK_FLAG_NO_UI;
748 if (context_pass==1)
749 sei.fMask |= SEE_MASK_INVOKEIDLIST;
750 sei.lpVerb = (verb_pass) ? NULL : szVerb;
751 sei.lpDirectory = szWorkingDirectory;
752 sei.nShow = SW_SHOWNORMAL;
753
754 if (ntry==0)
755 {
756 // this case works for most non-shortcuts
757 sei.fMask |= SEE_MASK_IDLIST;
758 sei.lpIDList = pidl;
759 }
760 else if (ntry==1)
761 {
762 // this case is required for *shortcuts to folders* to work
763 sei.lpFile = szPathAndFile;
764 }
765 else if (ntry==2)
766 {
767 // this case is required for *shortcuts to files* to work
768 sei.lpFile = szFilename2;
769 }
770
771 if (ShellExecuteEx(&sei))
772 return;
773 }
774 }
775 }
776 }
777
778 WNDPROC g_pOldWndProc;
779 LPCONTEXTMENU2 g_pIContext2or3;
780
HookWndProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp)781 LRESULT CALLBACK HookWndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
782 {
783 //UINT uItem;
784 //TCHAR szBuf[MAX_PATH];
785
786 switch (msg)
787 {
788 case WM_DRAWITEM:
789 case WM_MEASUREITEM:
790 if(wp) break; // not menu related
791 case WM_INITMENUPOPUP:
792 g_pIContext2or3->HandleMenuMsg(msg, wp, lp);
793 return (msg==WM_INITMENUPOPUP ? 0 : TRUE); // handled
794
795 /*case WM_MENUSELECT:
796 // if this is a shell item, get its descriptive text
797 uItem = (UINT) LOWORD(wp);
798 if(0 == (MF_POPUP & HIWORD(wp)) && uItem >= 1 && uItem <= 0x7fff)
799 {
800 g_pIContext2or3->GetCommandString(uItem-1, GCS_HELPTEXT,
801 NULL, szBuf, sizeof(szBuf)/sizeof(szBuf[0]) );
802
803 // set the status bar text
804 ((CFrameWnd*)(AfxGetApp()->m_pMainWnd))->SetMessageText(szBuf);
805 return 0;
806 }
807 break;*/
808
809 default:
810 break;
811 }
812
813 // for all untreated messages, call the original wndproc
814 return ::CallWindowProc(g_pOldWndProc, hWnd, msg, wp, lp);
815 }
816
DoExplorerMenu(HWND hwnd,LPITEMIDLIST pidlMain,POINT point)817 BOOL DoExplorerMenu (HWND hwnd, LPITEMIDLIST pidlMain, POINT point)
818 {
819 LPMALLOC pMalloc;
820 LPSHELLFOLDER psfFolder, psfNextFolder;
821 LPITEMIDLIST pidlItem, pidlNextItem, *ppidl;
822 LPCONTEXTMENU pContextMenu;
823 CMINVOKECOMMANDINFO ici;
824 UINT nCount, nCmd;
825 BOOL bResult;
826 HMENU hMenu;
827
828 //
829 // Get pointers to the shell's IMalloc interface and the desktop's
830 // IShellFolder interface.
831 //
832 bResult = FALSE;
833
834 if (!SUCCEEDED (SHGetMalloc (&pMalloc)))
835 return bResult;
836
837 if (!SUCCEEDED (SHGetDesktopFolder (&psfFolder))) {
838 pMalloc->Release();
839 return bResult;
840 }
841
842 if (nCount = GetItemCount (pidlMain)) // nCount must be > 0
843 {
844 //
845 // Initialize psfFolder with a pointer to the IShellFolder
846 // interface of the folder that contains the item whose context
847 // menu we're after, and initialize pidlItem with a pointer to
848 // the item's item ID. If nCount > 1, this requires us to walk
849 // the list of item IDs stored in pidlMain and bind to each
850 // subfolder referenced in the list.
851 //
852 pidlItem = pidlMain;
853
854 while (--nCount) {
855 //
856 // Create a 1-item item ID list for the next item in pidlMain.
857 //
858 pidlNextItem = DuplicateItem (pMalloc, pidlItem);
859 if (pidlNextItem == NULL) {
860 psfFolder->Release();
861 pMalloc->Release();
862 return bResult;
863 }
864
865 //
866 // Bind to the folder specified in the new item ID list.
867 //
868 if (!SUCCEEDED (psfFolder->BindToObject(pidlNextItem, NULL, IID_IShellFolder, (void**)&psfNextFolder))) // modified by RG
869 {
870 pMalloc->Free(pidlNextItem);
871 psfFolder->Release();
872 pMalloc->Release();
873 return bResult;
874 }
875
876 //
877 // Release the IShellFolder pointer to the parent folder
878 // and set psfFolder equal to the IShellFolder pointer for
879 // the current folder.
880 //
881 psfFolder->Release();
882 psfFolder = psfNextFolder;
883
884 //
885 // Release the storage for the 1-item item ID list we created
886 // just a moment ago and initialize pidlItem so that it points
887 // to the next item in pidlMain.
888 //
889 pMalloc->Free(pidlNextItem);
890 pidlItem = GetNextItem (pidlItem);
891 }
892
893 //
894 // Get a pointer to the item's IContextMenu interface and call
895 // IContextMenu::QueryContextMenu to initialize a context menu.
896 //
897 ppidl = &pidlItem;
898 if (SUCCEEDED (psfFolder->GetUIObjectOf(hwnd, 1, (LPCITEMIDLIST*)ppidl, IID_IContextMenu, NULL, (void**)&pContextMenu))) // modified by RG
899 {
900 // try to see if we can upgrade to an IContextMenu3
901 // or IContextMenu2 interface pointer:
902 int level = 1;
903 void *pCM = NULL;
904 if (pContextMenu->QueryInterface(IID_IContextMenu3, &pCM) == NOERROR)
905 {
906 pContextMenu->Release();
907 pContextMenu = (LPCONTEXTMENU)pCM;
908 level = 3;
909 }
910 else if (pContextMenu->QueryInterface(IID_IContextMenu2, &pCM) == NOERROR)
911 {
912 pContextMenu->Release();
913 pContextMenu = (LPCONTEXTMENU)pCM;
914 level = 2;
915 }
916
917 hMenu = CreatePopupMenu ();
918 if (SUCCEEDED (pContextMenu->QueryContextMenu(hMenu, 0, 1, 0x7FFF, CMF_EXPLORE)))
919 {
920 ClientToScreen (hwnd, &point);
921
922 // install the subclassing "hook", for versions 2 or 3
923 if (level >= 2)
924 {
925 g_pOldWndProc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (DWORD_PTR)HookWndProc);
926 g_pIContext2or3 = (LPCONTEXTMENU2)pContextMenu; // cast ok for ICMv3
927 }
928 else
929 {
930 g_pOldWndProc = NULL;
931 g_pIContext2or3 = NULL;
932 }
933
934 //
935 // Display the context menu.
936 //
937 nCmd = TrackPopupMenu (hMenu, TPM_LEFTALIGN |
938 TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD,
939 point.x, point.y, 0, hwnd, NULL);
940
941 // restore old wndProc
942 if (g_pOldWndProc)
943 {
944 SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG_PTR)g_pOldWndProc);
945 }
946
947 //
948 // If a command was selected from the menu, execute it.
949 //
950 if (nCmd >= 1 && nCmd <= 0x7fff)
951 {
952 ZeroMemory(&ici, sizeof(ici));
953 ici.cbSize = sizeof (CMINVOKECOMMANDINFO);
954 //ici.fMask = 0;
955 ici.hwnd = hwnd;
956 ici.lpVerb = MAKEINTRESOURCE (nCmd - 1);
957 //ici.lpParameters = NULL;
958 //ici.lpDirectory = NULL;
959 ici.nShow = SW_SHOWNORMAL;
960 //ici.dwHotKey = 0;
961 //ici.hIcon = NULL;
962
963 if (SUCCEEDED ( pContextMenu->InvokeCommand (&ici)))
964 bResult = TRUE;
965 }
966 /*else if (nCmd)
967 {
968 PostMessage(hwnd, WM_COMMAND, nCmd, NULL); // our command
969 }*/
970 }
971 DestroyMenu (hMenu);
972 pContextMenu->Release();
973 }
974 }
975
976 //
977 // Clean up and return.
978 //
979 psfFolder->Release();
980 pMalloc->Release();
981
982 return bResult;
983 }
984
985 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
986 //
987 // Note: a special thanks goes out to Jeff Prosise for writing & publishing
988 // the following code!
989 //
990 // FUNCTION: GetItemCount
991 //
992 // DESCRIPTION: Computes the number of item IDs in an item ID list.
993 //
994 // INPUT: pidl = Pointer to an item ID list.
995 //
996 // RETURNS: Number of item IDs in the list.
997 //
998 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
999
GetItemCount(LPITEMIDLIST pidl)1000 UINT GetItemCount (LPITEMIDLIST pidl)
1001 {
1002 USHORT nLen;
1003 UINT nCount;
1004
1005 nCount = 0;
1006 while ((nLen = pidl->mkid.cb) != 0) {
1007 pidl = GetNextItem (pidl);
1008 nCount++;
1009 }
1010 return nCount;
1011 }
1012
1013 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1014 //
1015 // Note: a special thanks goes out to Jeff Prosise for writing & publishing
1016 // the following code!
1017 //
1018 // FUNCTION: GetNextItem
1019 //
1020 // DESCRIPTION: Finds the next item in an item ID list.
1021 //
1022 // INPUT: pidl = Pointer to an item ID list.
1023 //
1024 // RETURNS: Pointer to the next item.
1025 //
1026 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1027
GetNextItem(LPITEMIDLIST pidl)1028 LPITEMIDLIST GetNextItem (LPITEMIDLIST pidl)
1029 {
1030 USHORT nLen;
1031
1032 if ((nLen = pidl->mkid.cb) == 0)
1033 return NULL;
1034
1035 return (LPITEMIDLIST) (((LPBYTE) pidl) + nLen);
1036 }
1037
1038 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1039 //
1040 // Note: a special thanks goes out to Jeff Prosise for writing & publishing
1041 // the following code!
1042 //
1043 // FUNCTION: DuplicateItem
1044 //
1045 // DESCRIPTION: Makes a copy of the next item in an item ID list.
1046 //
1047 // INPUT: pMalloc = Pointer to an IMalloc interface.
1048 // pidl = Pointer to an item ID list.
1049 //
1050 // RETURNS: Pointer to an ITEMIDLIST containing the copied item ID.
1051 //
1052 // NOTES: It is the caller's responsibility to free the memory
1053 // allocated by this function when the item ID is no longer
1054 // needed. Example:
1055 //
1056 // pidlItem = DuplicateItem (pMalloc, pidl);
1057 // .
1058 // .
1059 // .
1060 // pMalloc->lpVtbl->Free (pMalloc, pidlItem);
1061 //
1062 // Failure to free the ITEMIDLIST will result in memory
1063 // leaks.
1064 //
1065 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1066
DuplicateItem(LPMALLOC pMalloc,LPITEMIDLIST pidl)1067 LPITEMIDLIST DuplicateItem (LPMALLOC pMalloc, LPITEMIDLIST pidl)
1068 {
1069 USHORT nLen;
1070 LPITEMIDLIST pidlNew;
1071
1072 nLen = pidl->mkid.cb;
1073 if (nLen == 0)
1074 return NULL;
1075
1076 pidlNew = (LPITEMIDLIST) pMalloc->Alloc (
1077 nLen + sizeof (USHORT));
1078 if (pidlNew == NULL)
1079 return NULL;
1080
1081 CopyMemory (pidlNew, pidl, nLen);
1082 *((USHORT*) (((LPBYTE) pidlNew) + nLen)) = 0;
1083
1084 return pidlNew;
1085 }
1086
1087 //----------------------------------------------------------------------
1088 // A special thanks goes out to Jeroen-bart Engelen (Yeep) for providing
1089 // his source code for getting the position & label information for all
1090 // the icons on the desktop, as found below. See his article at
1091 // http://www.digiwar.com/scripts/renderpage.php?section=2&subsection=2
1092 //----------------------------------------------------------------------
1093
FindDesktopWindows(HWND * desktop_progman,HWND * desktopview_wnd,HWND * listview_wnd)1094 void FindDesktopWindows(HWND *desktop_progman, HWND *desktopview_wnd, HWND *listview_wnd)
1095 {
1096 *desktop_progman = NULL;
1097 *desktopview_wnd = NULL;
1098 *listview_wnd = NULL;
1099
1100 *desktop_progman = FindWindow(NULL, ("Program Manager"));
1101 if(*desktop_progman == NULL)
1102 {
1103 //MessageBox(NULL, "Unable to get the handle to the Program Manager.", "Fatal error", MB_OK|MB_ICONERROR);
1104 return;
1105 }
1106
1107 *desktopview_wnd = FindWindowEx(*desktop_progman, NULL, "SHELLDLL_DefView", NULL);
1108 if(*desktopview_wnd == NULL)
1109 {
1110 //MessageBox(NULL, "Unable to get the handle to the desktopview.", "Fatal error", MB_OK|MB_ICONERROR);
1111 return;
1112 }
1113
1114 // Thanks ef_ef_ef@yahoo.com for pointing out this works in NT 4 and not the way I did it originally.
1115 *listview_wnd = FindWindowEx(*desktopview_wnd, NULL, "SysListView32", NULL);
1116 if(*listview_wnd == NULL)
1117 {
1118 //MessageBox(NULL, "Unable to get the handle to the folderview.", "Fatal error", MB_OK|MB_ICONERROR);
1119 return;
1120 }
1121 }
1122
1123 //----------------------------------------------------------------------
1124
GetDesktopIconSize()1125 int GetDesktopIconSize()
1126 {
1127 int ret = 32;
1128
1129 // reads the key: HKEY_CURRENT_USER\Control Panel, Desktop\WindowMetrics\Shell Icon Size
1130 unsigned char buf[64];
1131 unsigned long len = sizeof(buf);
1132 DWORD type;
1133 HKEY key;
1134
1135 if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, "Control Panel\\Desktop\\WindowMetrics", 0, KEY_READ, &key))
1136 {
1137 if (ERROR_SUCCESS == RegQueryValueEx(key, "Shell Icon Size", NULL, &type, (unsigned char*)buf, &len) &&
1138 type == REG_SZ)
1139 {
1140 int x = _atoi_l((char*)buf, g_use_C_locale);
1141 if (x>0 && x<=128)
1142 ret = x;
1143 }
1144
1145 RegCloseKey(key);
1146 }
1147
1148 return ret;
1149 }
1150
1151 //----------------------------------------------------------------------
1152
1153 // handy functions for populating Combo Boxes:
SelectItemByValue(HWND ctrl,DWORD value)1154 int SelectItemByValue(HWND ctrl, DWORD value)
1155 {
1156 int count = SendMessage(ctrl, CB_GETCOUNT, 0, 0);
1157 for (int i=0; i<count; i++)
1158 {
1159 DWORD value_i = SendMessage( ctrl, CB_GETITEMDATA, i, 0);
1160 if (value_i == value)
1161 {
1162 SendMessage( ctrl, CB_SETCURSEL, i, 0);
1163 return i;
1164 }
1165 }
1166 return -1;
1167 }
1168
ReadCBValue(HWND hwnd,DWORD ctrl_id,int * pRetValue)1169 bool ReadCBValue(HWND hwnd, DWORD ctrl_id, int* pRetValue)
1170 {
1171 if (!pRetValue)
1172 return false;
1173 HWND ctrl = GetDlgItem( hwnd, ctrl_id );
1174 int t = SendMessage( ctrl, CB_GETCURSEL, 0, 0);
1175 if (t == CB_ERR)
1176 return false;
1177 *pRetValue = (int)SendMessage( ctrl, CB_GETITEMDATA, t, 0);
1178 return true;
1179 }
1180
1181 D3DXCREATEFONTW pCreateFontW=0;
1182 D3DXMATRIXMULTIPLY pMatrixMultiply=0;
1183 D3DXMATRIXTRANSLATION pMatrixTranslation=0;
1184 D3DXMATRIXSCALING pMatrixScaling=0;
1185 D3DXMATRIXROTATION pMatrixRotationX=0, pMatrixRotationY=0, pMatrixRotationZ=0;
1186 D3DXCREATETEXTUREFROMFILEEXW pCreateTextureFromFileExW=0;
1187 D3DXMATRIXORTHOLH pMatrixOrthoLH = 0;
1188 D3DXCOMPILESHADER pCompileShader=0;
1189 D3DXMATRIXLOOKATLH pMatrixLookAtLH=0;
1190 D3DXCREATETEXTURE pCreateTexture=0;
1191 //----------------------------------------------------------------------
FindD3DX9(HWND winamp)1192 HMODULE FindD3DX9(HWND winamp)
1193 {
1194 HMODULE d3dx9 = (HMODULE)SendMessage(winamp,WM_WA_IPC, 0, IPC_GET_D3DX9);
1195 if (!d3dx9 || d3dx9 == (HMODULE)1)
1196 {
1197
1198 // TODO: benski> this is a quick-fix, we should call FindFirstFile() on the system directory
1199 d3dx9=NULL;
1200 if (!d3dx9) d3dx9 = LoadLibrary("d3dx9_36.dll");
1201 if (!d3dx9) d3dx9 = LoadLibrary("d3dx9_35.dll");
1202 if (!d3dx9) d3dx9 = LoadLibrary("d3dx9_34.dll");
1203 if (!d3dx9) d3dx9 = LoadLibrary("d3dx9_33.dll");
1204 if (!d3dx9) d3dx9 = LoadLibrary("d3dx9_32.dll");
1205 if (!d3dx9) d3dx9 = LoadLibrary("d3dx9_31.dll");
1206 if (!d3dx9) d3dx9 = LoadLibrary("d3dx9_30.dll");
1207 if (!d3dx9) d3dx9 = LoadLibrary("d3dx9_29.dll");
1208 if (!d3dx9) d3dx9 = LoadLibrary("d3dx9_28.dll");
1209 if (!d3dx9) d3dx9 = LoadLibrary("d3dx9_27.dll");
1210 if (!d3dx9) d3dx9 = LoadLibrary("d3dx9_26.dll");
1211 if (!d3dx9) d3dx9 = LoadLibrary("d3dx9_25.dll");
1212 if (!d3dx9) d3dx9 = LoadLibrary("d3dx9_24.dll");
1213 }
1214
1215 if (d3dx9)
1216 {
1217 pCreateFontW = (D3DXCREATEFONTW) GetProcAddress(d3dx9,"D3DXCreateFontW");
1218 pMatrixMultiply = (D3DXMATRIXMULTIPLY) GetProcAddress(d3dx9,"D3DXMatrixMultiply");
1219 pMatrixTranslation = (D3DXMATRIXTRANSLATION)GetProcAddress(d3dx9,"D3DXMatrixTranslation");
1220 pMatrixScaling = (D3DXMATRIXSCALING)GetProcAddress(d3dx9,"D3DXMatrixScaling");
1221 pMatrixRotationX = (D3DXMATRIXROTATION)GetProcAddress(d3dx9,"D3DXMatrixRotationX");
1222 pMatrixRotationY = (D3DXMATRIXROTATION)GetProcAddress(d3dx9,"D3DXMatrixRotationY");
1223 pMatrixRotationZ = (D3DXMATRIXROTATION)GetProcAddress(d3dx9,"D3DXMatrixRotationZ");
1224 pCreateTextureFromFileExW = (D3DXCREATETEXTUREFROMFILEEXW)GetProcAddress(d3dx9,"D3DXCreateTextureFromFileExW");
1225 pMatrixOrthoLH = (D3DXMATRIXORTHOLH)GetProcAddress(d3dx9,"D3DXMatrixOrthoLH");
1226 pCompileShader = (D3DXCOMPILESHADER)GetProcAddress(d3dx9,"D3DXCompileShader");
1227 pMatrixLookAtLH = (D3DXMATRIXLOOKATLH)GetProcAddress(d3dx9,"D3DXMatrixLookAtLH");
1228 pCreateTexture = (D3DXCREATETEXTURE)GetProcAddress(d3dx9,"D3DXCreateTexture");
1229
1230
1231
1232 }
1233
1234 return d3dx9;
1235 }
1236
GetWinampVersion(HWND winamp)1237 LRESULT GetWinampVersion(HWND winamp)
1238 {
1239 static LRESULT version=0;
1240 if (!version)
1241 version=SendMessage(winamp,WM_WA_IPC,0,0);
1242 return version;
1243 }
1244
GetTextResource(UINT id,int no_fallback)1245 void* GetTextResource(UINT id, int no_fallback){
1246 void* data = 0;
1247 HINSTANCE hinst = WASABI_API_LNG_HINST;
1248 HRSRC rsrc = FindResource(hinst,MAKEINTRESOURCE(id),"TEXT");
1249 if(!rsrc && !no_fallback) rsrc = FindResource((hinst = WASABI_API_ORIG_HINST),MAKEINTRESOURCE(id),"TEXT");
1250 if(rsrc){
1251 HGLOBAL resourceHandle = LoadResource(hinst,rsrc);
1252 data = LockResource(resourceHandle);
1253 }
1254 return data;
1255 }