diff --git a/src/resource.h b/src/resource.h index e4f17158..ba69e8ab 100644 --- a/src/resource.h +++ b/src/resource.h @@ -8,9 +8,10 @@ #define IDD_NOTIFICATION 104 #define IDD_LICENSE 105 #define IDD_ISO_EXTRACT 106 -#define IDS_VERSION 107 -#define IDI_UP 108 -#define IDI_DOWN 109 +#define IDD_LOG 107 +#define IDS_VERSION 108 +#define IDI_UP 109 +#define IDI_DOWN 110 #define IDR_BR_MBR_BIN 200 #define IDR_FD_COMMAND_COM 300 #define IDR_FD_KERNEL_SYS 301 @@ -77,6 +78,10 @@ #define IDC_NOTIFICATION_LINE 1042 #define IDC_ADVANCED 1043 #define IDC_ADVANCED_GROUP 1044 +#define IDC_LOG 1045 +#define IDC_LOG_EDIT 1050 +#define IDC_LOG_SAVE 1051 +#define IDC_LOG_CLEAR 1052 // Next default values for new objects // @@ -85,7 +90,7 @@ #define _APS_NO_MFC 1 #define _APS_NEXT_RESOURCE_VALUE 110 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1045 +#define _APS_NEXT_CONTROL_VALUE 1053 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/src/rufus.c b/src/rufus.c index dea9e07d..37499201 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -87,6 +87,7 @@ static const char* ClusterSizeLabel[] = { "512 bytes", "1024 bytes","2048 bytes" "1024 kilobytes","2048 kilobytes","4096 kilobytes","8192 kilobytes","16 megabytes","32 megabytes" }; static BOOL existing_key = FALSE; // For LGP set/restore static BOOL iso_size_check = TRUE; +static BOOL log_displayed = FALSE; static int selection_default; BOOL enable_fixed_disks = FALSE, advanced_mode = TRUE; @@ -95,12 +96,12 @@ BOOL enable_fixed_disks = FALSE, advanced_mode = TRUE; */ HINSTANCE hMainInstance; HWND hMainDialog; -char szFolderPath[MAX_PATH]; +char szFolderPath[MAX_PATH], app_dir[MAX_PATH]; char* iso_path = NULL; float fScale = 1.0f; int default_fs; -HWND hDeviceList, hCapacity, hFileSystem, hClusterSize, hLabel, hDOSType, hNBPasses; -HWND hISOProgressDlg = NULL, hISOProgressBar, hISOFileName, hDiskID; +HWND hDeviceList, hCapacity, hFileSystem, hClusterSize, hLabel, hDOSType, hNBPasses, hLog = NULL; +HWND hISOProgressDlg = NULL, hLogDlg = NULL, hISOProgressBar, hISOFileName, hDiskID; BOOL use_own_vesamenu = FALSE, detect_fakes = TRUE, mbr_selected_by_user = FALSE; int rufus_version[4]; extern char szStatusMessage[256]; @@ -379,7 +380,7 @@ static BOOL GetDriveInfo(void) nb_partitions++; uprintf("Partition %d:\n", i+1); part_type = DriveLayout->PartitionEntry[i].Mbr.PartitionType; - uprintf(" Type: %s (0x%02x)\n Size: %s\n Boot: %s\n Recognized: %s\n Hidden Sectors: %d\n", + uprintf(" Type: %s (0x%02x)\r\n Size: %s\r\n Boot: %s\r\n Recognized: %s\r\n Hidden Sectors: %d\n", GetPartitionType(part_type), part_type, size_to_hr(DriveLayout->PartitionEntry[i].PartitionLength), DriveLayout->PartitionEntry[i].Mbr.BootIndicator?"Yes":"No", DriveLayout->PartitionEntry[i].Mbr.RecognizedPartition?"Yes":"No", @@ -1078,6 +1079,67 @@ static void EnableControls(BOOL bEnable) SetDlgItemTextA(hMainDialog, IDCANCEL, bEnable?"Close":"Cancel"); } +/* Callback for the log window */ +BOOL CALLBACK LogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + HDC hdc; + HFONT hf; + long lfHeight; + DWORD log_size; + char *log_buffer, *filepath; + + switch (message) { + case WM_INITDIALOG: + hLog = GetDlgItem(hDlg, IDC_LOG_EDIT); + // Increase the size of our log textbox to MAX_LOG_SIZE (unsigned word) + PostMessage(hLog, EM_LIMITTEXT, MAX_LOG_SIZE , 0); + // Set the font to Unicode so that we can display anything + hdc = GetDC(NULL); + lfHeight = -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72); + ReleaseDC(NULL, hdc); + hf = CreateFontA(lfHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, + DEFAULT_CHARSET, 0, 0, PROOF_QUALITY, 0, "Arial Unicode MS"); + SendDlgItemMessageA(hDlg, IDC_LOG_EDIT, WM_SETFONT, (WPARAM)hf, TRUE); + return TRUE; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDCANCEL: + ShowWindow(hDlg, SW_HIDE); + log_displayed = FALSE; + return TRUE; + case IDC_LOG_CLEAR: + SetWindowTextA(hLog, ""); + return TRUE; + case IDC_LOG_SAVE: + log_size = GetWindowTextLengthU(hLog); + log_buffer = (char*)malloc(log_size); + if (log_buffer != NULL) { + log_size = GetDlgItemTextU(hDlg, IDC_LOG_EDIT, log_buffer, log_size); + if (log_size == 0) { + uprintf("Nothing to save.\n"); + } else { + log_size--; // remove NULL terminator + filepath = FileDialog(TRUE, app_dir, "rufus.log", "log", "Rufus log"); + if (filepath != NULL) { + FileIO(TRUE, filepath, &log_buffer, &log_size); + } + safe_free(filepath); + } + safe_free(log_buffer); + } else { + uprintf("Could not allocate buffer to save log\n"); + } + break; + } + break; + case WM_CLOSE: + ShowWindow(hDlg, SW_HIDE); + log_displayed = FALSE; + return TRUE; + } + return FALSE; +} + /* * Timer in the right part of the status area */ @@ -1171,7 +1233,7 @@ DWORD WINAPI ISOScanThread(LPVOID param) safe_free(iso_path); goto out; } - uprintf("ISO label: '%s'\n size: %lld bytes, 4GB:%c, bootmgr:%c, winpe:%c (/minint:%c), isolinux:%c, old vesa:%c\n", + uprintf("ISO label: '%s'\r\n size: %lld bytes, 4GB:%c, bootmgr:%c, winpe:%c (/minint:%c), isolinux:%c, old vesa:%c\n", iso_report.label, iso_report.projected_size, iso_report.has_4GB_file?'Y':'N', iso_report.has_bootmgr?'Y':'N', IS_WINPE(iso_report.winpe)?'Y':'N', (iso_report.uses_minint)?'Y':'N', iso_report.has_isolinux?'Y':'N', iso_report.has_old_vesamenu?'Y':'N'); @@ -1249,7 +1311,7 @@ void MoveControl(int nID, float vertical_shift) // Toggle "advanced" mode void ToggleAdvanced(void) { - float dialog_shift = 60.0f; + float dialog_shift = 59.0f; RECT rect; POINT point; int toggle; @@ -1268,7 +1330,11 @@ void ToggleAdvanced(void) MoveControl(IDC_START, dialog_shift); MoveControl(IDC_PROGRESS, dialog_shift); MoveControl(IDC_ABOUT, dialog_shift); + MoveControl(IDC_LOG, dialog_shift); MoveControl(IDCANCEL, dialog_shift); +#ifdef RUFUS_TEST + MoveControl(IDC_TEST, dialog_shift); +#endif // Hide or show the various advanced options toggle = advanced_mode?SW_SHOW:SW_HIDE; @@ -1421,10 +1487,13 @@ void InitDialog(HWND hDlg) static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { DRAWITEMSTRUCT* pDI; - int nDeviceIndex, fs, i; + POINT Point; + RECT DialogRect, DesktopRect; + int nDeviceIndex, fs, i, nWidth, nHeight; static DWORD DeviceNum = 0; wchar_t wtmp[128], wstr[MAX_PATH]; static UINT uDOSChecked = BST_CHECKED; + static BOOL first_log_display = TRUE; switch (message) { @@ -1437,6 +1506,8 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA break; case WM_INITDIALOG: + // Create the log window (hidden) + hLogDlg = CreateDialogA(hMainInstance, MAKEINTRESOURCEA(IDD_LOG), hDlg, (DLGPROC)LogProc); InitDialog(hDlg); GetUSBDevices(0); return (INT_PTR)TRUE; @@ -1451,7 +1522,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA switch(pDI->itemID) { case 0: // left part DrawTextExU(pDI->hDC, szStatusMessage, -1, &pDI->rcItem, - DT_LEFT|DT_END_ELLIPSIS, NULL); + DT_LEFT|DT_END_ELLIPSIS|DT_PATH_ELLIPSIS, NULL); return (INT_PTR)TRUE; case 1: // right part SetTextColor(pDI->hDC, GetSysColor(COLOR_3DSHADOW)); @@ -1497,6 +1568,27 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA case IDC_ABOUT: CreateAboutBox(); break; + case IDC_LOG: + // Place the log Window to the right of our dialog on first display + if (first_log_display) { + GetClientRect(GetDesktopWindow(), &DesktopRect); + GetWindowRect(hLogDlg, &DialogRect); + nWidth = DialogRect.right - DialogRect.left; + nHeight = DialogRect.bottom - DialogRect.top; + GetWindowRect(hDlg, &DialogRect); + // TODO: adjust for high DPI + Point.x = min(DialogRect.right + 10, DesktopRect.right - nWidth); + Point.y = max(DialogRect.top, DesktopRect.top - nHeight); + MoveWindow(hLogDlg, Point.x, Point.y, nWidth, nHeight, FALSE); + first_log_display = FALSE; + } + // Display the log Window + log_displayed = !log_displayed; + ShowWindow(hLogDlg, log_displayed?SW_SHOW:SW_HIDE); + // Set focus on the start button + SendMessage(hMainDialog, WM_NEXTDLGCTL, (WPARAM)FALSE, 0); + SendMessage(hMainDialog, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hMainDialog, IDC_START), TRUE); + break; #ifdef RUFUS_TEST case IDC_TEST: break; @@ -1741,7 +1833,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA SetTaskbarProgressState(TASKBAR_ERROR); PrintStatus(0, FALSE, "FAILED"); Notification(MSG_ERROR, "Error", "Error: %s.%s", StrError(FormatStatus), - (strchr(StrError(FormatStatus), '\n') != NULL)?"":"\nFor more information, please try DebugView."); + (strchr(StrError(FormatStatus), '\n') != NULL)?"":"\nFor more information, please check the log."); } return (INT_PTR)TRUE; } @@ -1775,6 +1867,9 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine // Initialize COM for folder selection CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + // Retrieve the current application directory + GetCurrentDirectoryU(MAX_PATH, app_dir); + // Set the Windows version DetectWindowsVersion(); diff --git a/src/rufus.h b/src/rufus.h index 1db714d2..fce96327 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -34,6 +34,7 @@ #define MAX_DRIVES 16 #define MAX_TOOLTIPS 32 #define MAX_PROGRESS (0xFFFF-1) // leave room for 1 more for insta-progress workaround +#define MAX_LOG_SIZE 0x7FFFFFFE #define PROPOSEDLABEL_TOLERANCE 0.10 #define FS_DEFAULT FS_FAT32 #define WHITE RGB(255,255,255) @@ -187,8 +188,8 @@ enum WindowsVersion { * Globals */ extern HINSTANCE hMainInstance; -extern HWND hMainDialog, hStatus, hDeviceList, hCapacity; -extern HWND hFileSystem, hClusterSize, hLabel, hDOSType, hNBPasses; +extern HWND hMainDialog, hLogDlg, hStatus, hDeviceList, hCapacity; +extern HWND hFileSystem, hClusterSize, hLabel, hDOSType, hNBPasses, hLog; extern HWND hISOProgressDlg, hISOProgressBar, hISOFileName, hDiskID; extern float fScale; extern char szFolderPath[MAX_PATH]; @@ -233,6 +234,7 @@ extern BOOL UnmountDrive(HANDLE hDrive); extern BOOL CreateProgress(void); extern BOOL SetAutorun(const char* path); extern char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_desc); +extern BOOL FileIO(BOOL save, char* path, char** buffer, DWORD* size); extern LONG GetEntryWidth(HWND hDropDown, const char* entry); extern BOOL DownloadFile(const char* url, const char* file); extern char* get_token_data(const char* filename, const char* token); @@ -278,7 +280,7 @@ static __inline HMODULE GetDLLHandle(char* szDLLName) #define PF_INIT(proc, dllname) pf##proc = (proc##_t) GetProcAddress(GetDLLHandle(#dllname), #proc) #define PF_INIT_OR_OUT(proc, dllname) \ PF_INIT(proc, dllname); if (pf##proc == NULL) { \ - uprintf("unable to access %s DLL: %s", #dllname, \ + uprintf("Unable to access %s DLL: %s\n", #dllname, \ WindowsErrorString()); goto out; } /* Clang/MinGW32 has an issue with intptr_t */ diff --git a/src/rufus.rc b/src/rufus.rc index 8786ff03..32c67a43 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -30,7 +30,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 206, 316 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW -CAPTION "Rufus v1.2.0.178" +CAPTION "Rufus v1.2.0.179" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,94,278,50,14 @@ -56,13 +56,14 @@ BEGIN COMBOBOX IDC_NBPASSES,119,159,49,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_DOSTYPE,119,183,49,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "...",IDC_SELECT_ISO,171,182,22,14,BS_ICON - PUSHBUTTON "Test",IDC_TEST,62,278,20,14,NOT WS_VISIBLE + PUSHBUTTON "T",IDC_TEST,80,278,12,14,NOT WS_VISIBLE CONTROL "Use Rufus MBR with BIOS ID:",IDC_RUFUS_MBR,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,13,222,106,10 PUSHBUTTON "",IDC_ADVANCED,63,148,14,10,BS_TOP | BS_FLAT GROUPBOX "Advanced Options",IDC_ADVANCED_GROUP,7,210,192,42,NOT WS_VISIBLE COMBOBOX IDC_DISK_ID,119,220,73,30,CBS_DROPDOWNLIST | NOT WS_VISIBLE | WS_VSCROLL | WS_TABSTOP CONTROL "Add fixes for old BIOSes (extra partition, align, etc.)",IDC_EXTRA_PARTITION, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,235,184,10 + PUSHBUTTON "Log",IDC_LOG,62,278,18,14 END IDD_ABOUTBOX DIALOGEX 0, 0, 287, 195 @@ -76,7 +77,7 @@ BEGIN DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP CONTROL "http://rufus.akeo.ie",IDC_ABOUT_RUFUS_URL, "SysLink",WS_TABSTOP,46,47,114,9 - LTEXT "Version 1.2.0 (Build 178)",IDC_STATIC,46,19,78,8 + LTEXT "Version 1.2.0 (Build 179)",IDC_STATIC,46,19,78,8 PUSHBUTTON "License...",IDC_ABOUT_LICENSE,46,175,50,14,WS_GROUP EDITTEXT IDC_ABOUT_COPYRIGHTS,46,107,235,63,ES_MULTILINE | ES_READONLY | WS_VSCROLL LTEXT "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8 @@ -116,6 +117,17 @@ BEGIN EDITTEXT IDC_LICENSE_TEXT,7,7,321,176,ES_MULTILINE | ES_READONLY | WS_VSCROLL END +IDD_LOG DIALOGEX 0, 0, 366, 280 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION +CAPTION "Log" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + EDITTEXT IDC_LOG_EDIT,0,0,366,252,ES_MULTILINE | ES_READONLY | NOT WS_BORDER | WS_VSCROLL,WS_EX_STATICEDGE + PUSHBUTTON "Clear Log",IDC_LOG_CLEAR,204,259,50,14 + PUSHBUTTON "Save Log",IDC_LOG_SAVE,259,259,50,14 + PUSHBUTTON "Close",IDCANCEL,314,259,50,14 +END + #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// @@ -211,6 +223,10 @@ BEGIN IDD_LICENSE, DIALOG BEGIN END + + IDD_LOG, DIALOG + BEGIN + END END #endif // APSTUDIO_INVOKED @@ -221,8 +237,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,2,0,178 - PRODUCTVERSION 1,2,0,178 + FILEVERSION 1,2,0,179 + PRODUCTVERSION 1,2,0,179 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -239,13 +255,13 @@ BEGIN BEGIN VALUE "CompanyName", "akeo.ie" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.2.0.178" + VALUE "FileVersion", "1.2.0.179" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "1.2.0.178" + VALUE "ProductVersion", "1.2.0.179" END END BLOCK "VarFileInfo" diff --git a/src/stdio.c b/src/stdio.c index 53726b06..71437b9e 100644 --- a/src/stdio.c +++ b/src/stdio.c @@ -22,6 +22,7 @@ #endif #include +#include #include #include #include @@ -56,7 +57,11 @@ void _uprintf(const char *format, ...) *p++ = '\n'; *p = '\0'; + // Send output to Windows debug facility OutputDebugStringA(buf); + // Send output to our log Window + Edit_SetSel(hLog, MAX_LOG_SIZE, MAX_LOG_SIZE); + Edit_ReplaceSelU(hLog, buf); } #endif diff --git a/src/stdlg.c b/src/stdlg.c index 6a10c2bd..1c450f3b 100644 --- a/src/stdlg.c +++ b/src/stdlg.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "rufus.h" #include "msapi_utf8.h" @@ -139,6 +140,57 @@ void StrArrayDestroy(StrArray* arr) safe_free(arr->Table); } +/* + * Retrieve the SID of the current user. The returned PSID must be freed by the caller using LocalFree() + */ +static PSID GetSID(void) { + TOKEN_USER* tu = NULL; + DWORD len; + HANDLE token; + PSID ret = NULL; + char* psid_string = NULL; + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) { + uprintf("OpenProcessToken failed: %s\n", WindowsErrorString()); + return NULL; + } + + if (!GetTokenInformation(token, TokenUser, tu, 0, &len)) { + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + uprintf("GetTokenInformation (pre) failed: %s\n", WindowsErrorString()); + return NULL; + } + tu = (TOKEN_USER*)calloc(1, len); + } + if (tu == NULL) { + return NULL; + } + + if (GetTokenInformation(token, TokenUser, tu, len, &len)) { + /* + * now of course, the interesting thing is that if you return tu->User.Sid + * but free tu, the PSID pointer becomes invalid after a while. + * The workaround? Convert to string then back to PSID + */ + if (!ConvertSidToStringSidA(tu->User.Sid, &psid_string)) { + uprintf("Unable to convert SID to string: %s\n", WindowsErrorString()); + ret = NULL; + } else { + if (!ConvertStringSidToSidA(psid_string, &ret)) { + uprintf("Unable to convert string back to SID: %s\n", WindowsErrorString()); + ret = NULL; + } + // MUST use LocalFree() + LocalFree(psid_string); + } + } else { + ret = NULL; + uprintf("GetTokenInformation (real) failed: %s\n", WindowsErrorString()); + } + free(tu); + return ret; +} + /* * We need a sub-callback to read the content of the edit box on exit and update * our path, else if what the user typed does match the selection, it is discarded. @@ -224,13 +276,13 @@ void BrowseForFolder(void) { hr = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_INPROC, &IID_IFileOpenDialog, (LPVOID)&pfod); if (FAILED(hr)) { - uprintf("CoCreateInstance for FileOpenDialog failed: error %X", hr); + uprintf("CoCreateInstance for FileOpenDialog failed: error %X\n", hr); pfod = NULL; // Just in case goto fallback; } hr = pfod->lpVtbl->SetOptions(pfod, FOS_PICKFOLDERS); if (FAILED(hr)) { - uprintf("Failed to set folder option for FileOpenDialog: error %X", hr); + uprintf("Failed to set folder option for FileOpenDialog: error %X\n", hr); goto fallback; } // Set the initial folder (if the path is invalid, will simply use last) @@ -266,17 +318,17 @@ void BrowseForFolder(void) { tmp_path = wchar_to_utf8(wpath); CoTaskMemFree(wpath); if (tmp_path == NULL) { - uprintf("Could not convert path"); + uprintf("Could not convert path\n"); } else { safe_strcpy(szFolderPath, MAX_PATH, tmp_path); safe_free(tmp_path); } } else { - uprintf("Failed to set folder option for FileOpenDialog: error %X", hr); + uprintf("Failed to set folder option for FileOpenDialog: error %X\n", hr); } } else if ((hr & 0xFFFF) != ERROR_CANCELLED) { // If it's not a user cancel, assume the dialog didn't show and fallback - uprintf("could not show FileOpenDialog: error %X", hr); + uprintf("Could not show FileOpenDialog: error %X\n", hr); goto fallback; } pfod->lpVtbl->Release(pfod); @@ -301,6 +353,76 @@ fallback: } } +/* + * read or write I/O to a file + * buffer is allocated by the procedure. path is UTF-8 + */ +BOOL FileIO(BOOL save, char* path, char** buffer, DWORD* size) +{ + SECURITY_ATTRIBUTES s_attr, *ps = NULL; + SECURITY_DESCRIPTOR s_desc; + PSID sid = NULL; + HANDLE handle; + BOOL r; + BOOL ret = FALSE; + + // Change the owner from admin to regular user + sid = GetSID(); + if ( (sid != NULL) + && InitializeSecurityDescriptor(&s_desc, SECURITY_DESCRIPTOR_REVISION) + && SetSecurityDescriptorOwner(&s_desc, sid, FALSE) ) { + s_attr.nLength = sizeof(SECURITY_ATTRIBUTES); + s_attr.bInheritHandle = FALSE; + s_attr.lpSecurityDescriptor = &s_desc; + ps = &s_attr; + } else { + uprintf("Could not set security descriptor: %s\n", WindowsErrorString()); + } + + if (!save) { + *buffer = NULL; + } + handle = CreateFileU(path, save?GENERIC_WRITE:GENERIC_READ, FILE_SHARE_READ, + ps, save?CREATE_ALWAYS:OPEN_EXISTING, 0, NULL); + + if (handle == INVALID_HANDLE_VALUE) { + uprintf("Could not %s file '%s'\n", save?"create":"open", path); + goto out; + } + + if (save) { + r = WriteFile(handle, *buffer, *size, size, NULL); + } else { + *size = GetFileSize(handle, NULL); + *buffer = (char*)malloc(*size); + if (*buffer == NULL) { + uprintf("Could not allocate buffer for reading file\n"); + goto out; + } + r = ReadFile(handle, *buffer, *size, size, NULL); + } + + if (!r) { + uprintf("I/O Error: %s\n", WindowsErrorString()); + goto out; + } + + PrintStatus(0, TRUE, "%s '%s'", save?"Saved":"Opened", path); + ret = TRUE; + +out: + CloseHandle(handle); + if (!ret) { + // Only leave a buffer allocated if successful + *size = 0; + if (!save) { + safe_free(*buffer); + } + } + return ret; +} + + /* * Return the UTF8 path of a file selected through a load or save dialog * Will use the newer IFileOpenDialog if *compiled* for Vista or later @@ -385,7 +507,7 @@ char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_des } } else if ((hr & 0xFFFF) != ERROR_CANCELLED) { // If it's not a user cancel, assume the dialog didn't show and fallback - uprintf("could not show FileOpenDialog: error %X\n", hr); + uprintf("Could not show FileOpenDialog: error %X\n", hr); goto fallback; } pfd->lpVtbl->Release(pfd); @@ -612,7 +734,7 @@ INT_PTR CALLBACK NotificationCallback(HWND hDlg, UINT message, WPARAM wParam, LP CenterDialog(hDlg); // Change the default icon if (Static_SetIcon(GetDlgItem(hDlg, IDC_NOTIFICATION_ICON), hMessageIcon) == 0) { - uprintf("could not set dialog icon"); + uprintf("Could not set dialog icon\n"); } // Set the dialog title if (szMessageTitle != NULL) { @@ -918,7 +1040,7 @@ BOOL CreateTaskbarList(void) // Create the taskbar icon progressbar hr = CoCreateInstance(&my_CLSID_TaskbarList, NULL, CLSCTX_ALL, &my_IID_ITaskbarList3, (LPVOID)&ptbl); if (FAILED(hr)) { - uprintf("CoCreateInstance for TaskbarList failed: error %X", hr); + uprintf("CoCreateInstance for TaskbarList failed: error %X\n", hr); ptbl = NULL; return FALSE; }