mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[core] basic dialog
* UAC elevation and Aero controls enabled
This commit is contained in:
parent
a3c0ac9b6a
commit
f5cd7de095
6 changed files with 781 additions and 0 deletions
24
common_controls_and_elevation.manifest
Normal file
24
common_controls_and_elevation.manifest
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||||
|
<dependency>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity
|
||||||
|
type="win32"
|
||||||
|
name="Microsoft.Windows.Common-Controls"
|
||||||
|
version="6.0.0.0"
|
||||||
|
processorArchitecture="*"
|
||||||
|
publicKeyToken="6595b64144ccf1df"
|
||||||
|
language="*"
|
||||||
|
/>
|
||||||
|
</dependentAssembly>
|
||||||
|
</dependency>
|
||||||
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<security>
|
||||||
|
<requestedPrivileges>
|
||||||
|
<requestedExecutionLevel
|
||||||
|
level="highestAvailable"
|
||||||
|
uiAccess="false"/>
|
||||||
|
</requestedPrivileges>
|
||||||
|
</security>
|
||||||
|
</trustInfo>
|
||||||
|
</assembly>
|
562
msapi_utf8.h
Normal file
562
msapi_utf8.h
Normal file
|
@ -0,0 +1,562 @@
|
||||||
|
/*
|
||||||
|
* MSAPI_UTF8: Common API calls using UTF-8 strings
|
||||||
|
* Compensating for what Microsoft should have done a long long time ago.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2011 Pete Batard <pete@akeo.ie>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <shlobj.h>
|
||||||
|
#include <commdlg.h>
|
||||||
|
#include <shellapi.h>
|
||||||
|
#include <setupapi.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define wchar_to_utf8_no_alloc(wsrc, dest, dest_size) \
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, wsrc, -1, dest, dest_size, NULL, NULL)
|
||||||
|
#define utf8_to_wchar_no_alloc(src, wdest, wdest_size) \
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, src, -1, wdest, wdest_size)
|
||||||
|
#define Edit_ReplaceSelU(hCtrl, str) ((void)SendMessageLU(hCtrl, EM_REPLACESEL, (WPARAM)FALSE, str))
|
||||||
|
#define ComboBox_AddStringU(hCtrl, str) ((int)(DWORD)SendMessageLU(hCtrl, CB_ADDSTRING, (WPARAM)FALSE, str))
|
||||||
|
#define ComboBox_GetTextU(hCtrl, str, max_str) GetWindowTextU(hCtrl, str, max_str)
|
||||||
|
#define GetSaveFileNameU(p) GetOpenSaveFileNameU(p, TRUE)
|
||||||
|
#define GetOpenFileNameU(p) GetOpenSaveFileNameU(p, FALSE)
|
||||||
|
#define ListView_SetItemTextU(hwndLV,i,iSubItem_,pszText_) { LVITEMW _ms_wlvi; _ms_wlvi.iSubItem = iSubItem_; \
|
||||||
|
_ms_wlvi.pszText = utf8_to_wchar(pszText_); \
|
||||||
|
SNDMSG((hwndLV),LVM_SETITEMTEXTW,(WPARAM)(i),(LPARAM)&_ms_wlvi); sfree(_ms_wlvi.pszText);}
|
||||||
|
|
||||||
|
#define sfree(p) do {if (p != NULL) {free((void*)(p)); p = NULL;}} while(0)
|
||||||
|
#define wconvert(p) wchar_t* w ## p = utf8_to_wchar(p)
|
||||||
|
#define walloc(p, size) wchar_t* w ## p = calloc(size, sizeof(wchar_t))
|
||||||
|
#define wfree(p) sfree(w ## p)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Converts an UTF-16 string to UTF8 (allocate returned string)
|
||||||
|
* Returns NULL on error
|
||||||
|
*/
|
||||||
|
static __inline char* wchar_to_utf8(const wchar_t* wstr)
|
||||||
|
{
|
||||||
|
int size = 0;
|
||||||
|
char* str = NULL;
|
||||||
|
|
||||||
|
// Find out the size we need to allocate for our converted string
|
||||||
|
size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
|
||||||
|
if (size <= 1) // An empty string would be size 1
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if ((str = (char*)calloc(size, 1)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (wchar_to_utf8_no_alloc(wstr, str, size) != size) {
|
||||||
|
sfree(str);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Converts an UTF8 string to UTF-16 (allocate returned string)
|
||||||
|
* Returns NULL on error
|
||||||
|
*/
|
||||||
|
static __inline wchar_t* utf8_to_wchar(const char* str)
|
||||||
|
{
|
||||||
|
int size = 0;
|
||||||
|
wchar_t* wstr = NULL;
|
||||||
|
|
||||||
|
// Find out the size we need to allocate for our converted string
|
||||||
|
size = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
|
||||||
|
if (size <= 1) // An empty string would be size 1
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if ((wstr = (wchar_t*)calloc(size, sizeof(wchar_t))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (utf8_to_wchar_no_alloc(str, wstr, size) != size) {
|
||||||
|
sfree(wstr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return wstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline DWORD FormatMessageU(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId,
|
||||||
|
DWORD dwLanguageId, char* lpBuffer, DWORD nSize, va_list *Arguments)
|
||||||
|
{
|
||||||
|
DWORD ret = 0, err = ERROR_INVALID_DATA;
|
||||||
|
walloc(lpBuffer, nSize);
|
||||||
|
ret = FormatMessageW(dwFlags, lpSource, dwMessageId, dwLanguageId, wlpBuffer, nSize, Arguments);
|
||||||
|
err = GetLastError();
|
||||||
|
if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpBuffer, lpBuffer, nSize)) == 0)) {
|
||||||
|
err = GetLastError();
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
wfree(lpBuffer);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendMessage, with LPARAM as UTF-8 string
|
||||||
|
static __inline LRESULT SendMessageLU(HWND hWnd, UINT Msg, WPARAM wParam, const char* lParam)
|
||||||
|
{
|
||||||
|
LRESULT ret = FALSE;
|
||||||
|
DWORD err = ERROR_INVALID_DATA;
|
||||||
|
wconvert(lParam);
|
||||||
|
ret = SendMessageW(hWnd, Msg, wParam, (LPARAM)wlParam);
|
||||||
|
err = GetLastError();
|
||||||
|
wfree(lParam);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline BOOL SHGetPathFromIDListU(LPCITEMIDLIST pidl, char* pszPath)
|
||||||
|
{
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
DWORD err = ERROR_INVALID_DATA;
|
||||||
|
walloc(pszPath, MAX_PATH);
|
||||||
|
ret = SHGetPathFromIDListW(pidl, wpszPath);
|
||||||
|
err = GetLastError();
|
||||||
|
if ((ret) && (wchar_to_utf8_no_alloc(wpszPath, pszPath, MAX_PATH) == 0)) {
|
||||||
|
err = GetLastError();
|
||||||
|
ret = FALSE;
|
||||||
|
}
|
||||||
|
wfree(pszPath);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline HWND CreateWindowU(char* lpClassName, char* lpWindowName,
|
||||||
|
DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent,
|
||||||
|
HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
|
||||||
|
{
|
||||||
|
HWND ret = NULL;
|
||||||
|
DWORD err = ERROR_INVALID_DATA;
|
||||||
|
wconvert(lpClassName);
|
||||||
|
wconvert(lpWindowName);
|
||||||
|
ret = CreateWindowW(wlpClassName, wlpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
|
||||||
|
err = GetLastError();
|
||||||
|
wfree(lpClassName);
|
||||||
|
wfree(lpWindowName);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline int GetWindowTextU(HWND hWnd, char* lpString, int nMaxCount)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
DWORD err = ERROR_INVALID_DATA;
|
||||||
|
walloc(lpString, nMaxCount);
|
||||||
|
ret = GetWindowTextW(hWnd, wlpString, nMaxCount);
|
||||||
|
err = GetLastError();
|
||||||
|
if ( (ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpString, lpString, nMaxCount)) == 0) ) {
|
||||||
|
err = GetLastError();
|
||||||
|
}
|
||||||
|
wfree(lpString);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline BOOL SetWindowTextU(HWND hWnd, const char* lpString)
|
||||||
|
{
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
DWORD err = ERROR_INVALID_DATA;
|
||||||
|
wconvert(lpString);
|
||||||
|
ret = SetWindowTextW(hWnd, wlpString);
|
||||||
|
err = GetLastError();
|
||||||
|
wfree(lpString);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline int GetWindowTextLengthU(HWND hWnd)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
DWORD err = ERROR_INVALID_DATA;
|
||||||
|
wchar_t* wbuf = NULL;
|
||||||
|
char* buf = NULL;
|
||||||
|
|
||||||
|
ret = GetWindowTextLengthW(hWnd);
|
||||||
|
err = GetLastError();
|
||||||
|
if (ret == 0) goto out;
|
||||||
|
wbuf = calloc(ret, sizeof(wchar_t));
|
||||||
|
err = GetLastError();
|
||||||
|
if (wbuf == NULL) {
|
||||||
|
err = ERROR_OUTOFMEMORY; ret = 0; goto out;
|
||||||
|
}
|
||||||
|
ret = GetWindowTextW(hWnd, wbuf, ret);
|
||||||
|
err = GetLastError();
|
||||||
|
if (ret == 0) goto out;
|
||||||
|
buf = wchar_to_utf8(wbuf);
|
||||||
|
err = GetLastError();
|
||||||
|
if (buf == NULL) {
|
||||||
|
err = ERROR_OUTOFMEMORY; ret = 0; goto out;
|
||||||
|
}
|
||||||
|
ret = (int)strlen(buf) + 2; // GetDlgItemText seems to add a character
|
||||||
|
err = GetLastError();
|
||||||
|
out:
|
||||||
|
sfree(wbuf);
|
||||||
|
sfree(buf);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline UINT GetDlgItemTextU(HWND hDlg, int nIDDlgItem, char* lpString, int nMaxCount)
|
||||||
|
{
|
||||||
|
UINT ret = 0;
|
||||||
|
DWORD err = ERROR_INVALID_DATA;
|
||||||
|
walloc(lpString, nMaxCount);
|
||||||
|
ret = GetDlgItemTextW(hDlg, nIDDlgItem, wlpString, nMaxCount);
|
||||||
|
err = GetLastError();
|
||||||
|
if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpString, lpString, nMaxCount)) == 0)) {
|
||||||
|
err = GetLastError();
|
||||||
|
}
|
||||||
|
wfree(lpString);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline BOOL SetDlgItemTextU(HWND hDlg, int nIDDlgItem, const char* lpString)
|
||||||
|
{
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
DWORD err = ERROR_INVALID_DATA;
|
||||||
|
wconvert(lpString);
|
||||||
|
ret = SetDlgItemTextW(hDlg, nIDDlgItem, wlpString);
|
||||||
|
err = GetLastError();
|
||||||
|
wfree(lpString);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline HANDLE CreateFileU(const char* lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||||
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
||||||
|
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
|
||||||
|
{
|
||||||
|
HANDLE ret = INVALID_HANDLE_VALUE;
|
||||||
|
DWORD err = ERROR_INVALID_DATA;
|
||||||
|
wconvert(lpFileName);
|
||||||
|
ret = CreateFileW(wlpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
|
||||||
|
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
||||||
|
err = GetLastError();
|
||||||
|
wfree(lpFileName);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline BOOL DeleteFileU(const char* lpFileName)
|
||||||
|
{
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
DWORD err = ERROR_INVALID_DATA;
|
||||||
|
wconvert(lpFileName);
|
||||||
|
ret = DeleteFileW(wlpFileName);
|
||||||
|
err = GetLastError();
|
||||||
|
wfree(lpFileName);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function differs from regular GetTextExtentPoint in that it uses a zero terminated string
|
||||||
|
static __inline BOOL GetTextExtentPointU(HDC hdc, const char* lpString, LPSIZE lpSize)
|
||||||
|
{
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
DWORD err = ERROR_INVALID_DATA;
|
||||||
|
wconvert(lpString);
|
||||||
|
ret = GetTextExtentPointW(hdc, wlpString, (int)wcslen(wlpString)+1, lpSize);
|
||||||
|
err = GetLastError();
|
||||||
|
wfree(lpString);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline DWORD GetCurrentDirectoryU(DWORD nBufferLength, char* lpBuffer)
|
||||||
|
{
|
||||||
|
DWORD ret = 0, err = ERROR_INVALID_DATA;
|
||||||
|
walloc(lpBuffer, nBufferLength);
|
||||||
|
ret = GetCurrentDirectoryW(nBufferLength, wlpBuffer);
|
||||||
|
err = GetLastError();
|
||||||
|
if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpBuffer, lpBuffer, nBufferLength)) == 0)) {
|
||||||
|
err = GetLastError();
|
||||||
|
}
|
||||||
|
wfree(lpBuffer);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline DWORD GetFullPathNameU(const char* lpFileName, DWORD nBufferLength, char* lpBuffer, char** lpFilePart)
|
||||||
|
{
|
||||||
|
DWORD ret = 0, err = ERROR_INVALID_DATA;
|
||||||
|
wchar_t* wlpFilePart;
|
||||||
|
wconvert(lpFileName);
|
||||||
|
walloc(lpBuffer, nBufferLength);
|
||||||
|
|
||||||
|
// lpFilePart is not supported
|
||||||
|
if (lpFilePart != NULL) goto out;
|
||||||
|
|
||||||
|
ret = GetFullPathNameW(wlpFileName, nBufferLength, wlpBuffer, &wlpFilePart);
|
||||||
|
err = GetLastError();
|
||||||
|
if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpBuffer, lpBuffer, nBufferLength)) == 0)) {
|
||||||
|
err = GetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
wfree(lpBuffer);
|
||||||
|
wfree(lpFileName);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline DWORD GetFileAttributesU(const char* lpFileName)
|
||||||
|
{
|
||||||
|
DWORD ret = 0xFFFFFFFF, err = ERROR_INVALID_DATA;
|
||||||
|
wconvert(lpFileName);
|
||||||
|
ret = GetFileAttributesW(wlpFileName);
|
||||||
|
err = GetLastError();
|
||||||
|
wfree(lpFileName);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline int SHCreateDirectoryExU(HWND hwnd, const char* pszPath, SECURITY_ATTRIBUTES *psa)
|
||||||
|
{
|
||||||
|
int ret = ERROR_INVALID_DATA;
|
||||||
|
DWORD err = ERROR_INVALID_DATA;
|
||||||
|
wconvert(pszPath);
|
||||||
|
ret = SHCreateDirectoryExW(hwnd, wpszPath, psa);
|
||||||
|
err = GetLastError();
|
||||||
|
wfree(pszPath);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline BOOL ShellExecuteExU(SHELLEXECUTEINFOA* lpExecInfo)
|
||||||
|
{
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
DWORD err = ERROR_INVALID_DATA;
|
||||||
|
SHELLEXECUTEINFOW wExecInfo;
|
||||||
|
|
||||||
|
// Because we're lazy, we'll assume that the A and W structs inherently have the same size
|
||||||
|
if (lpExecInfo->cbSize != sizeof(SHELLEXECUTEINFOW)) {
|
||||||
|
SetLastError(ERROR_BAD_LENGTH); return FALSE;
|
||||||
|
}
|
||||||
|
memcpy(&wExecInfo, lpExecInfo, lpExecInfo->cbSize);
|
||||||
|
wExecInfo.lpVerb = utf8_to_wchar(lpExecInfo->lpVerb);
|
||||||
|
wExecInfo.lpFile = utf8_to_wchar(lpExecInfo->lpFile);
|
||||||
|
wExecInfo.lpParameters = utf8_to_wchar(lpExecInfo->lpParameters);
|
||||||
|
wExecInfo.lpDirectory = utf8_to_wchar(lpExecInfo->lpDirectory);
|
||||||
|
if (wExecInfo.fMask & SEE_MASK_CLASSNAME) {
|
||||||
|
wExecInfo.lpClass = utf8_to_wchar(lpExecInfo->lpClass);
|
||||||
|
} else {
|
||||||
|
wExecInfo.lpClass = NULL;
|
||||||
|
}
|
||||||
|
ret = ShellExecuteExW(&wExecInfo);
|
||||||
|
err = GetLastError();
|
||||||
|
// Copy the returned values back
|
||||||
|
lpExecInfo->hInstApp = wExecInfo.hInstApp;
|
||||||
|
lpExecInfo->hProcess = wExecInfo.hProcess;
|
||||||
|
sfree(wExecInfo.lpVerb);
|
||||||
|
sfree(wExecInfo.lpFile);
|
||||||
|
sfree(wExecInfo.lpParameters);
|
||||||
|
sfree(wExecInfo.lpDirectory);
|
||||||
|
sfree(wExecInfo.lpClass);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Doesn't support LPSTARTUPINFOEX struct
|
||||||
|
static __inline BOOL CreateProcessU(const char* lpApplicationName, const char* lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||||
|
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags,
|
||||||
|
LPVOID lpEnvironment, const char* lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo,
|
||||||
|
LPPROCESS_INFORMATION lpProcessInformation)
|
||||||
|
{
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
DWORD err = ERROR_INVALID_DATA;
|
||||||
|
STARTUPINFOW wStartupInfo;
|
||||||
|
wconvert(lpApplicationName);
|
||||||
|
wconvert(lpCommandLine);
|
||||||
|
wconvert(lpCurrentDirectory);
|
||||||
|
|
||||||
|
// Because we're lazy, we'll assume that the A and W structs inherently have the same size
|
||||||
|
// Also prevents the use of STARTUPINFOEX
|
||||||
|
if (lpStartupInfo->cb != sizeof(STARTUPINFOW)) {
|
||||||
|
err = ERROR_BAD_LENGTH; goto out;
|
||||||
|
}
|
||||||
|
memcpy(&wStartupInfo, lpStartupInfo, lpStartupInfo->cb);
|
||||||
|
wStartupInfo.lpDesktop = utf8_to_wchar(lpStartupInfo->lpDesktop);
|
||||||
|
wStartupInfo.lpTitle = utf8_to_wchar(lpStartupInfo->lpTitle);
|
||||||
|
ret = CreateProcessW(wlpApplicationName, wlpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles,
|
||||||
|
dwCreationFlags, lpEnvironment, wlpCurrentDirectory, &wStartupInfo, lpProcessInformation);
|
||||||
|
err = GetLastError();
|
||||||
|
sfree(wStartupInfo.lpDesktop);
|
||||||
|
sfree(wStartupInfo.lpTitle);
|
||||||
|
out:
|
||||||
|
wfree(lpApplicationName);
|
||||||
|
wfree(lpCommandLine);
|
||||||
|
wfree(lpCurrentDirectory);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: when used, nFileOffset & nFileExtension MUST be provided
|
||||||
|
// in number of Unicode characters, NOT number of UTF-8 bytes
|
||||||
|
static __inline BOOL WINAPI GetOpenSaveFileNameU(LPOPENFILENAMEA lpofn, BOOL save)
|
||||||
|
{
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
DWORD err = ERROR_INVALID_DATA;
|
||||||
|
size_t i, len;
|
||||||
|
OPENFILENAMEW wofn;
|
||||||
|
memset(&wofn, 0, sizeof(wofn));
|
||||||
|
wofn.lStructSize = sizeof(wofn);
|
||||||
|
wofn.hwndOwner = lpofn->hwndOwner;
|
||||||
|
wofn.hInstance = lpofn->hInstance;
|
||||||
|
|
||||||
|
// No support for custom filters
|
||||||
|
if (lpofn->lpstrCustomFilter != NULL) goto out;
|
||||||
|
|
||||||
|
// Count on Microsoft to use an moronic scheme for filters
|
||||||
|
// that relies on NULL separators and double NULL terminators
|
||||||
|
if (lpofn->lpstrFilter != NULL) {
|
||||||
|
// Replace the NULLs by something that can be converted
|
||||||
|
for (i=0; ; i++) {
|
||||||
|
if (lpofn->lpstrFilter[i] == 0) {
|
||||||
|
((char*)lpofn->lpstrFilter)[i] = '\r';
|
||||||
|
if (lpofn->lpstrFilter[i+1] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wofn.lpstrFilter = utf8_to_wchar(lpofn->lpstrFilter);
|
||||||
|
// And revert
|
||||||
|
len = wcslen(wofn.lpstrFilter); // don't use in the loop as it would be reevaluated
|
||||||
|
for (i=0; i<len; i++) {
|
||||||
|
if (wofn.lpstrFilter[i] == '\r') {
|
||||||
|
((wchar_t*)wofn.lpstrFilter)[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
len = strlen(lpofn->lpstrFilter);
|
||||||
|
for (i=0; i<len; i++) {
|
||||||
|
if (lpofn->lpstrFilter[i] == '\r') {
|
||||||
|
((char*)lpofn->lpstrFilter)[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wofn.lpstrFilter = NULL;
|
||||||
|
}
|
||||||
|
wofn.nMaxCustFilter = lpofn->nMaxCustFilter;
|
||||||
|
wofn.nFilterIndex = lpofn->nFilterIndex;
|
||||||
|
wofn.lpstrFile = calloc(lpofn->nMaxFile, sizeof(wchar_t));
|
||||||
|
utf8_to_wchar_no_alloc(lpofn->lpstrFile, wofn.lpstrFile, lpofn->nMaxFile);
|
||||||
|
wofn.nMaxFile = lpofn->nMaxFile;
|
||||||
|
wofn.lpstrFileTitle = calloc(lpofn->nMaxFileTitle, sizeof(wchar_t));
|
||||||
|
utf8_to_wchar_no_alloc(lpofn->lpstrFileTitle, wofn.lpstrFileTitle, lpofn->nMaxFileTitle);
|
||||||
|
wofn.nMaxFileTitle = lpofn->nMaxFileTitle;
|
||||||
|
wofn.lpstrInitialDir = utf8_to_wchar(lpofn->lpstrInitialDir);
|
||||||
|
wofn.lpstrTitle = utf8_to_wchar(lpofn->lpstrTitle);
|
||||||
|
wofn.Flags = lpofn->Flags;
|
||||||
|
wofn.nFileOffset = lpofn->nFileOffset;
|
||||||
|
wofn.nFileExtension = lpofn->nFileExtension;
|
||||||
|
wofn.lpstrDefExt = utf8_to_wchar(lpofn->lpstrDefExt);
|
||||||
|
wofn.lCustData = lpofn->lCustData;
|
||||||
|
wofn.lpfnHook = lpofn->lpfnHook;
|
||||||
|
wofn.lpTemplateName = utf8_to_wchar(lpofn->lpTemplateName);
|
||||||
|
wofn.pvReserved = lpofn->pvReserved;
|
||||||
|
wofn.dwReserved = lpofn->dwReserved;
|
||||||
|
wofn.FlagsEx = lpofn->FlagsEx;
|
||||||
|
|
||||||
|
if (save) {
|
||||||
|
ret = GetSaveFileNameW(&wofn);
|
||||||
|
} else {
|
||||||
|
ret = GetOpenFileNameW(&wofn);
|
||||||
|
}
|
||||||
|
err = GetLastError();
|
||||||
|
if ( (ret)
|
||||||
|
&& ( (wchar_to_utf8_no_alloc(wofn.lpstrFile, lpofn->lpstrFile, lpofn->nMaxFile) == 0)
|
||||||
|
|| (wchar_to_utf8_no_alloc(wofn.lpstrFileTitle, lpofn->lpstrFileTitle, lpofn->nMaxFileTitle) == 0) ) ) {
|
||||||
|
err = GetLastError();
|
||||||
|
ret = FALSE;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
sfree(wofn.lpstrDefExt);
|
||||||
|
sfree(wofn.lpstrFile);
|
||||||
|
sfree(wofn.lpstrFileTitle);
|
||||||
|
sfree(wofn.lpstrFilter);
|
||||||
|
sfree(wofn.lpstrInitialDir);
|
||||||
|
sfree(wofn.lpstrTitle);
|
||||||
|
sfree(wofn.lpTemplateName);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern BOOL WINAPI UpdateDriverForPlugAndPlayDevicesW(HWND hwndParent, LPCWSTR HardwareId,
|
||||||
|
LPCWSTR FullInfPath, DWORD InstallFlags, PBOOL bRebootRequired);
|
||||||
|
|
||||||
|
static __inline BOOL UpdateDriverForPlugAndPlayDevicesU(HWND hwndParent, const char* HardwareId, const char* FullInfPath,
|
||||||
|
DWORD InstallFlags, PBOOL bRebootRequired)
|
||||||
|
{
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
DWORD err = ERROR_INVALID_DATA;
|
||||||
|
wconvert(HardwareId);
|
||||||
|
wconvert(FullInfPath);
|
||||||
|
ret = UpdateDriverForPlugAndPlayDevicesW(hwndParent, wHardwareId, wFullInfPath, InstallFlags, bRebootRequired);
|
||||||
|
err = GetLastError();
|
||||||
|
wfree(HardwareId);
|
||||||
|
wfree(FullInfPath);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline BOOL SetupCopyOEMInfU(const char* SourceInfFileName, const char* OEMSourceMediaLocation, DWORD OEMSourceMediaType,
|
||||||
|
DWORD CopyStyle, char* DestinationInfFileName, DWORD DestinationInfFileNameSize,
|
||||||
|
PDWORD RequiredSize, PTSTR DestinationInfFileNameComponent)
|
||||||
|
{
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
DWORD err = ERROR_INVALID_DATA;
|
||||||
|
wconvert(SourceInfFileName);
|
||||||
|
wconvert(OEMSourceMediaLocation);
|
||||||
|
walloc(DestinationInfFileName, DestinationInfFileNameSize);
|
||||||
|
|
||||||
|
// DestinationInfFileNameComponent is not supported
|
||||||
|
if (DestinationInfFileNameComponent != NULL) goto out;
|
||||||
|
|
||||||
|
ret = SetupCopyOEMInfW(wSourceInfFileName, wOEMSourceMediaLocation, OEMSourceMediaType, CopyStyle,
|
||||||
|
wDestinationInfFileName, DestinationInfFileNameSize, RequiredSize, NULL);
|
||||||
|
err = GetLastError();
|
||||||
|
if ((ret != FALSE) && ((ret = wchar_to_utf8_no_alloc(wDestinationInfFileName, DestinationInfFileName, DestinationInfFileNameSize)) == 0)) {
|
||||||
|
err = GetLastError();
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
wfree(SourceInfFileName);
|
||||||
|
wfree(OEMSourceMediaLocation);
|
||||||
|
wfree(DestinationInfFileName);
|
||||||
|
SetLastError(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline FILE* fopenU(const char* filename, const char* mode)
|
||||||
|
{
|
||||||
|
FILE* ret = NULL;
|
||||||
|
wconvert(filename);
|
||||||
|
wconvert(mode);
|
||||||
|
ret = _wfopen(wfilename, wmode);
|
||||||
|
wfree(filename);
|
||||||
|
wfree(mode);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
BIN
resource.h
Normal file
BIN
resource.h
Normal file
Binary file not shown.
149
usbdos.c
Normal file
149
usbdos.c
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* USBDOS: USB DOS bootable stick creation utility
|
||||||
|
* Copyright (c) 2011 Pete Batard <pete@akeo.ie>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <windowsx.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <commctrl.h>
|
||||||
|
|
||||||
|
#include "msapi_utf8.h"
|
||||||
|
#include "resource.h"
|
||||||
|
#include "usbdos.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Globals
|
||||||
|
*/
|
||||||
|
HINSTANCE main_instance;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Main dialog callback
|
||||||
|
*/
|
||||||
|
static INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
switch (message) {
|
||||||
|
|
||||||
|
case WM_DEVICECHANGE:
|
||||||
|
return (INT_PTR)TRUE;
|
||||||
|
|
||||||
|
case WM_INITDIALOG:
|
||||||
|
return (INT_PTR)TRUE;
|
||||||
|
|
||||||
|
case WM_COMMAND:
|
||||||
|
switch(LOWORD(wParam)) {
|
||||||
|
case IDC_CLOSE:
|
||||||
|
PostQuitMessage(0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return (INT_PTR)FALSE;
|
||||||
|
}
|
||||||
|
return (INT_PTR)TRUE;
|
||||||
|
|
||||||
|
case WM_CLOSE:
|
||||||
|
PostQuitMessage(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
return (INT_PTR)FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Center a dialog with regards to the main application Window or the desktop
|
||||||
|
*/
|
||||||
|
void CenterDialog(HWND hDialog)
|
||||||
|
{
|
||||||
|
POINT Point;
|
||||||
|
HWND hParent;
|
||||||
|
RECT DialogRect;
|
||||||
|
RECT ParentRect;
|
||||||
|
int nWidth;
|
||||||
|
int nHeight;
|
||||||
|
|
||||||
|
// Get the size of the dialog box.
|
||||||
|
GetWindowRect(hDialog, &DialogRect);
|
||||||
|
|
||||||
|
// Get the parent
|
||||||
|
hParent = GetParent(hDialog);
|
||||||
|
if (hParent == NULL) {
|
||||||
|
hParent = GetDesktopWindow();
|
||||||
|
}
|
||||||
|
GetClientRect(hParent, &ParentRect);
|
||||||
|
|
||||||
|
// Calculate the height and width of the current dialog
|
||||||
|
nWidth = DialogRect.right - DialogRect.left;
|
||||||
|
nHeight = DialogRect.bottom - DialogRect.top;
|
||||||
|
|
||||||
|
// Find the center point and convert to screen coordinates.
|
||||||
|
Point.x = (ParentRect.right - ParentRect.left) / 2;
|
||||||
|
Point.y = (ParentRect.bottom - ParentRect.top) / 2;
|
||||||
|
ClientToScreen(hParent, &Point);
|
||||||
|
|
||||||
|
// Calculate the new x, y starting point.
|
||||||
|
Point.x -= nWidth / 2;
|
||||||
|
Point.y -= nHeight / 2 + 35;
|
||||||
|
|
||||||
|
// Move the window.
|
||||||
|
MoveWindow(hDialog, Point.x, Point.y, nWidth, nHeight, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Application Entrypoint
|
||||||
|
*/
|
||||||
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||||
|
{
|
||||||
|
HANDLE mutex = NULL;
|
||||||
|
HWND hDlg = NULL;
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
// Prevent 2 applications from running at the same time
|
||||||
|
mutex = CreateMutexA(NULL, TRUE, "Global/USBDOS");
|
||||||
|
if ((mutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS))
|
||||||
|
{
|
||||||
|
MessageBoxA(NULL, "Another USBDOS application is running.\n"
|
||||||
|
"Please close the first application before running another one.",
|
||||||
|
"Other instance detected", MB_ICONSTOP);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save instance of the application for further reference
|
||||||
|
main_instance = hInstance;
|
||||||
|
|
||||||
|
// Initialize COM for folder selection
|
||||||
|
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||||
|
|
||||||
|
// Create the main Window
|
||||||
|
if ( (hDlg = CreateDialogA(hInstance, MAKEINTRESOURCEA(IDD_DIALOG), NULL, main_callback)) == NULL ) {
|
||||||
|
MessageBoxA(NULL, "Could not create Window", "DialogBox failure", MB_ICONSTOP);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
CenterDialog(hDlg);
|
||||||
|
ShowWindow(hDlg, SW_SHOWNORMAL);
|
||||||
|
UpdateWindow(hDlg);
|
||||||
|
|
||||||
|
// Do our own event processing
|
||||||
|
while(GetMessage(&msg, NULL, 0, 0)) {
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
CloseHandle(mutex);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
46
usbdos.h
Normal file
46
usbdos.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* USBDOS: USB DOS bootable stick creation utility
|
||||||
|
* Copyright (c) 2011 Pete Batard <pete@akeo.ie>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if !defined(bool)
|
||||||
|
#define bool BOOL
|
||||||
|
#endif
|
||||||
|
#if !defined(true)
|
||||||
|
#define true TRUE
|
||||||
|
#endif
|
||||||
|
#if !defined(false)
|
||||||
|
#define false FALSE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define APP_VERSION "USBDOS v0.1.0.1"
|
||||||
|
|
||||||
|
#define safe_free(p) do {free((void*)p); p = NULL;} while(0)
|
||||||
|
#define safe_min(a, b) min((size_t)(a), (size_t)(b))
|
||||||
|
#define safe_strcp(dst, dst_max, src, count) do {memcpy(dst, src, safe_min(count, dst_max)); \
|
||||||
|
((char*)dst)[safe_min(count, dst_max)-1] = 0;} while(0)
|
||||||
|
#define safe_strcpy(dst, dst_max, src) safe_strcp(dst, dst_max, src, safe_strlen(src)+1)
|
||||||
|
#define safe_strncat(dst, dst_max, src, count) strncat(dst, src, safe_min(count, dst_max - safe_strlen(dst) - 1))
|
||||||
|
#define safe_strcat(dst, dst_max, src) safe_strncat(dst, dst_max, src, safe_strlen(src)+1)
|
||||||
|
#define safe_strcmp(str1, str2) strcmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
|
||||||
|
#define safe_stricmp(str1, str2) _stricmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
|
||||||
|
#define safe_strncmp(str1, str2, count) strncmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2), count)
|
||||||
|
#define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
|
||||||
|
#define safe_sprintf _snprintf
|
||||||
|
#define safe_strlen(str) ((((char*)str)==NULL)?0:strlen(str))
|
||||||
|
#define safe_strdup _strdup
|
BIN
usbdos.rc
Normal file
BIN
usbdos.rc
Normal file
Binary file not shown.
Loading…
Reference in a new issue