diff --git a/common_controls_and_elevation.manifest b/common_controls_and_elevation.manifest new file mode 100644 index 00000000..ff5841ce --- /dev/null +++ b/common_controls_and_elevation.manifest @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + diff --git a/msapi_utf8.h b/msapi_utf8.h new file mode 100644 index 00000000..197c342d --- /dev/null +++ b/msapi_utf8.h @@ -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 + * + * 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 +#include +#include +#include +#include +#include + +#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; ilpstrFilter); + for (i=0; ilpstrFilter[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 diff --git a/resource.h b/resource.h new file mode 100644 index 00000000..6129a6e8 Binary files /dev/null and b/resource.h differ diff --git a/usbdos.c b/usbdos.c new file mode 100644 index 00000000..e5bfa85d --- /dev/null +++ b/usbdos.c @@ -0,0 +1,149 @@ +/* + * USBDOS: USB DOS bootable stick creation utility + * Copyright (c) 2011 Pete Batard + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/usbdos.h b/usbdos.h new file mode 100644 index 00000000..b54690b1 --- /dev/null +++ b/usbdos.h @@ -0,0 +1,46 @@ +/* + * USBDOS: USB DOS bootable stick creation utility + * Copyright (c) 2011 Pete Batard + * + * 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 . + */ + +#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)?"":str1), ((str2==NULL)?"":str2)) +#define safe_stricmp(str1, str2) _stricmp(((str1==NULL)?"":str1), ((str2==NULL)?"":str2)) +#define safe_strncmp(str1, str2, count) strncmp(((str1==NULL)?"":str1), ((str2==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 diff --git a/usbdos.rc b/usbdos.rc new file mode 100644 index 00000000..0e4ae43f Binary files /dev/null and b/usbdos.rc differ