foobar2000 SDK  2015-08-03
win32_misc.cpp
Go to the documentation of this file.
1 #include "stdafx.h"
2 
3 void registerclass_scope_delayed::toggle_on(UINT p_style,WNDPROC p_wndproc,int p_clsextra,int p_wndextra,HICON p_icon,HCURSOR p_cursor,HBRUSH p_background,const TCHAR * p_class_name,const TCHAR * p_menu_name) {
4  toggle_off();
5  WNDCLASS wc = {};
6  wc.style = p_style;
7  wc.lpfnWndProc = p_wndproc;
8  wc.cbClsExtra = p_clsextra;
9  wc.cbWndExtra = p_wndextra;
10  wc.hInstance = core_api::get_my_instance();
11  wc.hIcon = p_icon;
12  wc.hCursor = p_cursor;
13  wc.hbrBackground = p_background;
14  wc.lpszMenuName = p_menu_name;
15  wc.lpszClassName = p_class_name;
16  WIN32_OP_CRITICAL("RegisterClass", (m_class = RegisterClass(&wc)) != 0);
17 }
18 
20  if (m_class != 0) {
21  UnregisterClass((LPCTSTR)m_class,core_api::get_my_instance());
22  m_class = 0;
23  }
24 }
25 
26 
27 unsigned QueryScreenDPI() {
28  HDC dc = GetDC(0);
29  unsigned ret = GetDeviceCaps(dc,LOGPIXELSY);
30  ReleaseDC(0,dc);
31  return ret;
32 }
33 
34 
36  HDC dc = GetDC(0);
37  SIZE ret = { GetDeviceCaps(dc,LOGPIXELSY), GetDeviceCaps(dc,LOGPIXELSY) };
38  ReleaseDC(0,dc);
39  return ret;
40 }
41 
42 
43 bool IsMenuNonEmpty(HMENU menu) {
44  unsigned n,m=GetMenuItemCount(menu);
45  for(n=0;n<m;n++) {
46  if (GetSubMenu(menu,n)) return true;
47  if (!(GetMenuState(menu,n,MF_BYPOSITION)&MF_SEPARATOR)) return true;
48  }
49  return false;
50 }
51 
52 PFC_NORETURN PFC_NOINLINE void WIN32_OP_FAIL() {
53  const DWORD code = GetLastError();
54  PFC_ASSERT( code != NO_ERROR );
55  throw exception_win32(code);
56 }
57 
58 PFC_NORETURN PFC_NOINLINE void WIN32_OP_FAIL_CRITICAL(const char * what) {
59  const DWORD code = GetLastError();
60  PFC_ASSERT( code != NO_ERROR );
61  pfc::string_formatter msg; msg << what << " failure #" << (uint32_t)code;
62  TRACK_CODE(msg.get_ptr(), uBugCheck());
63 }
64 
65 #ifdef _DEBUG
66 void WIN32_OP_D_FAIL(const wchar_t * _Message, const wchar_t *_File, unsigned _Line) {
67  const DWORD code = GetLastError();
68  pfc::array_t<wchar_t> msgFormatted; msgFormatted.set_size(pfc::strlen_t(_Message) + 64);
69  wsprintfW(msgFormatted.get_ptr(), L"%s (code: %u)", _Message, code);
70  if (IsDebuggerPresent()) {
71  OutputDebugString(TEXT("WIN32_OP_D() failure:\n"));
72  OutputDebugString(msgFormatted.get_ptr());
73  OutputDebugString(TEXT("\n"));
74  pfc::crash();
75  }
76  _wassert(msgFormatted.get_ptr(),_File,_Line);
77 }
78 #endif
79 
80 
82  out.reset(); GetOSVersionStringAppend(out);
83 }
84 
85 static bool running_under_wine(void) {
86  HMODULE module = GetModuleHandle(_T("ntdll.dll"));
87  if (!module) return false;
88  return GetProcAddress(module, "wine_server_call") != NULL;
89 }
91  typedef const char *(__cdecl *t_wine_get_build_id)(void);
92  typedef void (__cdecl *t_wine_get_host_version)( const char **sysname, const char **release );
93  const HMODULE ntdll = GetModuleHandle(_T("ntdll.dll"));
94  if (ntdll == NULL) return false;
95  t_wine_get_build_id wine_get_build_id;
96  t_wine_get_host_version wine_get_host_version;
97  wine_get_build_id = (t_wine_get_build_id)GetProcAddress(ntdll, "wine_get_build_id");
98  wine_get_host_version = (t_wine_get_host_version)GetProcAddress(ntdll, "wine_get_host_version");
99  if (wine_get_build_id == NULL || wine_get_host_version == NULL) {
100  if (GetProcAddress(ntdll, "wine_server_call") != NULL) {
101  out << "wine (unknown version)";
102  return true;
103  }
104  return false;
105  }
106  const char * sysname = NULL; const char * release = NULL;
107  wine_get_host_version(&sysname, &release);
108  out << wine_get_build_id() << ", on: " << sysname << " / " << release;
109  return true;
110 }
112 
113  if (FetchWineInfoAppend(out)) return;
114 
115  OSVERSIONINFO ver = {}; ver.dwOSVersionInfoSize = sizeof(ver);
116  WIN32_OP( GetVersionEx(&ver) );
117  SYSTEM_INFO info = {};
118  GetNativeSystemInfo(&info);
119 
120  out << "Windows " << (int)ver.dwMajorVersion << "." << (int)ver.dwMinorVersion << "." << (int)ver.dwBuildNumber;
121  if (ver.szCSDVersion[0] != 0) out << " " << pfc::stringcvt::string_utf8_from_os(ver.szCSDVersion, PFC_TABSIZE(ver.szCSDVersion));
122 
123  switch(info.wProcessorArchitecture) {
124  case PROCESSOR_ARCHITECTURE_AMD64:
125  out << " x64"; break;
126  case PROCESSOR_ARCHITECTURE_IA64:
127  out << " IA64"; break;
128  case PROCESSOR_ARCHITECTURE_INTEL:
129  out << " x86"; break;
130  }
131 }
132 
133 
134 void SetDefaultMenuItem(HMENU p_menu,unsigned p_id) {
135  MENUITEMINFO info = {sizeof(info)};
136  info.fMask = MIIM_STATE;
137  GetMenuItemInfo(p_menu,p_id,FALSE,&info);
138  info.fState |= MFS_DEFAULT;
139  SetMenuItemInfo(p_menu,p_id,FALSE,&info);
140 }
141 
142 
143 bool SetClipboardDataBlock(UINT p_format,const void * p_block,t_size p_block_size) {
144  bool success = false;
145  if (OpenClipboard(NULL)) {
146  EmptyClipboard();
147  HANDLE handle = GlobalAlloc(GMEM_MOVEABLE,p_block_size);
148  if (handle == NULL) {
149  CloseClipboard();
150  throw std::bad_alloc();
151  }
152  {CGlobalLock lock(handle);memcpy(lock.GetPtr(),p_block,p_block_size);}
153  if (SetClipboardData(p_format,handle) == NULL) {
154  GlobalFree(handle);//todo?
155  } else {
156  success = true;
157  }
158  CloseClipboard();
159  }
160  return success;
161 }
162 
163 mutexScope::mutexScope(HANDLE hMutex_, abort_callback & abort) : hMutex(hMutex_) {
164  HANDLE h[2] = {hMutex, abort.get_abort_event()};
165  switch( WaitForMultipleObjects(2, h, FALSE, INFINITE) ) {
166  case WAIT_OBJECT_0:
167  break; // and enter
168  case WAIT_OBJECT_0+1:
169  throw exception_aborted();
170  default:
171  uBugCheck();
172  }
173 }
175  ReleaseMutex(hMutex);
176 }
177 
178 
179 
180 void winLocalFileScope::open( const char * inPath, file::ptr inReader, abort_callback & aborter) {
181  close();
182  if (inPath != NULL) {
183  if (_extract_native_path_ptr( inPath ) ) {
184  pfc::string8 prefixed;
185  pfc::winPrefixPath( prefixed, inPath );
186  m_path = pfc::stringcvt::string_wide_from_utf8( prefixed );
187  m_isTemp = false;
188  return;
189  }
190  }
191 
192  pfc::string8 tempPath;
193  if (!uGetTempPath( tempPath )) uBugCheck();
194  tempPath.add_filename( PFC_string_formatter() << pfc::print_guid( pfc::createGUID() ) << ".rar" );
195 
196  m_path = pfc::stringcvt::string_wide_from_utf8( tempPath );
197 
198  if (inReader.is_empty()) {
199  if (inPath == NULL) uBugCheck();
200  inReader = fileOpenReadExisting( inPath, aborter, 1.0 );
201  }
202 
203  file::ptr writer = fileOpenWriteNew( PFC_string_formatter() << "file://" << tempPath, aborter, 1.0 );
204  file::g_transfer_file( inReader , writer, aborter );
205  m_isTemp = true;
206 }
208  if (m_isTemp && m_path.length() > 0) {
209  pfc::lores_timer timer;
210  timer.start();
211  for(;;) {
212  if (DeleteFile( m_path.c_str() )) break;
213  if (timer.query() > 1.0) break;
214  Sleep(10);
215  }
216  }
217  m_path.clear();
218 }
219 
220 CMutex::CMutex(const TCHAR * name) {
221  WIN32_OP_CRITICAL( "CreateMutex", m_hMutex = CreateMutex(NULL, FALSE, name) );
222 }
224  CloseHandle(m_hMutex);
225 }
226 
228  SetLastError(0);
229  HANDLE hWait[2] = {hMutex, aborter.get_abort_event()};
230  switch(WaitForMultipleObjects( 2, hWait, FALSE, INFINITE ) ) {
231  case WAIT_FAILED:
232  WIN32_OP_FAIL_CRITICAL("WaitForSingleObject");
233  case WAIT_OBJECT_0:
234  return;
235  case WAIT_OBJECT_0 + 1:
236  PFC_ASSERT( aborter.is_aborting() );
237  throw exception_aborted();
238  default:
239  uBugCheck();
240  }
241 }
242 
243 void CMutex::Acquire( abort_callback& aborter ) {
244  AcquireByHandle( Handle(), aborter );
245 }
246 
248  ReleaseMutex( Handle() );
249 }
250 
251 
252 CMutexScope::CMutexScope(CMutex & mutex, DWORD timeOutMS, const char * timeOutBugMsg) : m_mutex(mutex) {
253  SetLastError(0);
254  const unsigned div = 4;
255  for(unsigned walk = 0; walk < div; ++walk) {
256  switch(WaitForSingleObject( m_mutex.Handle(), timeOutMS/div ) ) {
257  case WAIT_FAILED:
258  WIN32_OP_FAIL_CRITICAL("WaitForSingleObject");
259  case WAIT_OBJECT_0:
260  return;
261  case WAIT_TIMEOUT:
262  break;
263  default:
264  uBugCheck();
265  }
266  }
267  TRACK_CODE(timeOutBugMsg, uBugCheck());
268 }
269 
271  SetLastError(0);
272  switch(WaitForSingleObject( m_mutex.Handle(), INFINITE ) ) {
273  case WAIT_FAILED:
274  WIN32_OP_FAIL_CRITICAL("WaitForSingleObject");
275  case WAIT_OBJECT_0:
276  return;
277  default:
278  uBugCheck();
279  }
280 }
281 
283  mutex.Acquire( aborter );
284 }
285 
287  ReleaseMutex(m_mutex.Handle());
288 }
bool SetClipboardDataBlock(UINT p_format, const void *p_block, t_size p_block_size)
Definition: win32_misc.cpp:143
DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAll, DWORD dwMilliseconds)
Definition: pp-winapi.h:20
unsigned QueryScreenDPI()
Definition: win32_misc.cpp:27
const t_item * get_ptr() const
Definition: array.h:213
PFC_NORETURN PFC_NOINLINE void WIN32_OP_FAIL()
Definition: win32_misc.cpp:52
void SetDefaultMenuItem(HMENU p_menu, unsigned p_id)
Definition: win32_misc.cpp:134
void start()
Definition: timers.h:93
GUID createGUID()
Definition: guid.cpp:161
bool IsMenuNonEmpty(HMENU menu)
Definition: win32_misc.cpp:43
void toggle_on(UINT p_style, WNDPROC p_wndproc, int p_clsextra, int p_wndextra, HICON p_icon, HCURSOR p_cursor, HBRUSH p_background, const TCHAR *p_classname, const TCHAR *p_menuname)
Definition: win32_misc.cpp:3
static bool running_under_wine(void)
Definition: win32_misc.cpp:85
void info(const char *p_message)
Definition: console.cpp:4
HANDLE hMutex
Definition: win32_misc.h:290
void GetOSVersionString(pfc::string_base &out)
Definition: win32_misc.cpp:81
bool _extract_native_path_ptr(const char *&p_fspath)
Definition: filesystem.cpp:942
void GetOSVersionStringAppend(pfc::string_base &out)
Definition: win32_misc.cpp:111
string_wide_from_utf8_t string_wide_from_utf8
Definition: string_conv.h:160
Decoder Validator v1 readme Usage Select a single file handled by the decoder you want to select Utils Decoder Utils Tag Writer Validator or Utils Fuzzer from the context menu with randomly generated info In case of success(found problems with relevant tag writer implementations)
void * GetPtr() const
Definition: win-objects.h:77
void winPrefixPath(pfc::string_base &out, const char *p_path)
Definition: win-objects.cpp:55
void WIN32_OP_D_FAIL(const wchar_t *_Message, const wchar_t *_File, unsigned _Line)
Definition: win32_misc.cpp:66
typedef HANDLE(WINAPI *pPowerCreateRequest_t)(__in void *Context)
file_ptr fileOpenWriteNew(const char *p_path, abort_callback &p_abort, double p_timeout=0)
Definition: filesystem.h:586
::critical_section mutex
Definition: synchro_win.h:131
string_utf8_from_wide string_utf8_from_os
Definition: string_conv.h:517
const char * get_ptr() const
Definition: string_base.h:382
DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
Definition: pp-winapi.h:16
CMutex(const TCHAR *name=NULL)
Definition: win32_misc.cpp:220
t_size strlen_t(const t_char *p_string, t_size p_length=~0)
Definition: primitives.h:771
size_t t_size
Definition: int_types.h:48
void crash()
Definition: other.cpp:112
void set_size(t_size p_size)
Definition: array.h:104
HANDLE Handle()
Definition: win32_misc.h:356
SIZE QueryScreenDPIEx()
Definition: win32_misc.cpp:35
CMutex & m_mutex
Definition: win32_misc.h:373
void open(const char *inPath, file::ptr inReader, abort_callback &aborter)
Definition: win32_misc.cpp:180
static void AcquireByHandle(HANDLE hMutex, abort_callback &aborter)
Definition: win32_misc.cpp:227
mutexScope(HANDLE hMutex_, abort_callback &abort)
Definition: win32_misc.cpp:163
double query() const
Definition: timers.h:97
PFC_NORETURN PFC_NOINLINE void WIN32_OP_FAIL_CRITICAL(const char *what)
Definition: win32_misc.cpp:58
void Release()
Definition: win32_misc.cpp:247
file_ptr fileOpenReadExisting(const char *p_path, abort_callback &p_abort, double p_timeout=0)
Definition: filesystem.h:580
static bool FetchWineInfoAppend(pfc::string_base &out)
Definition: win32_misc.cpp:90
HINSTANCE get_my_instance()
Retrieves HINSTANCE of calling DLL.
void Acquire(abort_callback &aborter)
Definition: win32_misc.cpp:243
PFC_NORETURN void SHARED_EXPORT uBugCheck()
BOOL SHARED_EXPORT uGetTempPath(pfc::string_base &out)
CMutexScope(CMutex &mutex, DWORD timeOutMS, const char *timeOutBugMsg)
Definition: win32_misc.cpp:252
void add_filename(const char *fn)
Definition: string_base.h:257