foobar2000 SDK  2015-01-14
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 );
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 
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 
227 void CMutex::AcquireByHandle( HANDLE hMutex, abort_callback & aborter ) {
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 
270 CMutexScope::CMutexScope(CMutex & mutex) : m_mutex(mutex) {
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 
282 CMutexScope::CMutexScope(CMutex & mutex, abort_callback & aborter) : m_mutex(mutex) {
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
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:74
GUID createGUID()
Definition: guid.cpp:157
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
std::wstring m_path
Definition: win32_misc.h:347
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
void * GetPtr() const
Definition: win-objects.h:75
void winPrefixPath(pfc::string_base &out, const char *p_path)
Definition: win-objects.cpp:53
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:581
string_utf8_from_wide string_utf8_from_os
Definition: string_conv.h:517
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
string8_fastalloc string_formatter
Definition: string_base.h:614
void crash()
Definition: other.cpp:105
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:78
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:575
static bool FetchWineInfoAppend(pfc::string_base &out)
Definition: win32_misc.cpp:90
HANDLE m_hMutex
Definition: win32_misc.h:362
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:256