DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) { LARGE_INTEGER endTime64,ticksPerSecond,ticks; DWORDLONG ticksShifted,tickSecShifted; DWORD dwLog=16+0; DWORD dwRet; if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(&endTime64))) dwRet = (GetTickCount() - beginTime64.LowPart)*1; else { MyDoMinus64(&ticks,endTime64,beginTime64); QueryPerformanceFrequency(&ticksPerSecond); { ticksShifted = Int64ShrlMod32(*(DWORDLONG*)&ticks,dwLog); tickSecShifted = Int64ShrlMod32(*(DWORDLONG*)&ticksPerSecond,dwLog); } dwRet = (DWORD)((((DWORD)ticksShifted)*1000)/(DWORD)(tickSecShifted)); dwRet *=1; } return dwRet; }
ULONGLONG APIENTRY EngGetTickCount(VOID) { ULONG Multiplier; LARGE_INTEGER TickCount; /* Get the multiplier and current tick count */ KeQueryTickCount(&TickCount); Multiplier = SharedUserData->TickCountMultiplier; /* Convert to milliseconds and return */ return (Int64ShrlMod32(UInt32x32To64(Multiplier, TickCount.LowPart), 24) + (Multiplier * (TickCount.HighPart << 8))); }
/* Unit should be a power-of-2 (e.g. 1024 to report kilobytes) or 1 (to report bytes) */ static ulong getdiskspace(const char* path, ulong unit, BOOL freespace) { #if defined(_WIN32) char root[16]; DWORD TotalNumberOfClusters; DWORD NumberOfFreeClusters; DWORD BytesPerSector; DWORD SectorsPerCluster; ULARGE_INTEGER avail; ULARGE_INTEGER size; static HINSTANCE hK32; GetDiskFreeSpaceEx_t GetDiskFreeSpaceEx; if(hK32 == NULL) hK32 = LoadLibrary("KERNEL32"); GetDiskFreeSpaceEx = (GetDiskFreeSpaceEx_t)GetProcAddress(hK32,"GetDiskFreeSpaceExA"); if (GetDiskFreeSpaceEx!=NULL) { /* Windows 95-OSR2 or later */ if(!GetDiskFreeSpaceEx( path, /* pointer to the directory name */ &avail, /* receives the number of bytes on disk avail to the caller */ &size, /* receives the number of bytes on disk */ NULL)) /* receives the free bytes on disk */ return(0); if(freespace) size=avail; if(unit>1) size.QuadPart=Int64ShrlMod32(size.QuadPart,bit_num(unit)); #if defined(_ANONYMOUS_STRUCT) if(size.HighPart) #else if(size.u.HighPart) #endif return(0xffffffff); /* 4GB max */ #if defined(_ANONYMOUS_STRUCT) return(size.LowPart); #else return(size.u.LowPart); #endif } /* Windows 95 (old way), limited to 2GB */ sprintf(root,"%.3s",path); if(!GetDiskFreeSpace( root, /* pointer to root path */ (PDWORD)&SectorsPerCluster, /* pointer to sectors per cluster */ (PDWORD)&BytesPerSector, /* pointer to bytes per sector */ (PDWORD)&NumberOfFreeClusters, /* pointer to number of free clusters */ (PDWORD)&TotalNumberOfClusters /* pointer to total number of clusters */ )) return(0); if(freespace) TotalNumberOfClusters = NumberOfFreeClusters; if(unit>1) TotalNumberOfClusters/=unit; return(TotalNumberOfClusters*SectorsPerCluster*BytesPerSector); #elif defined(__solaris__) || (defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 300000000 /* NetBSD 3.0 */)) struct statvfs fs; unsigned long blocks; if (statvfs(path, &fs) < 0) return 0; if(freespace) blocks=fs.f_bavail; else blocks=fs.f_blocks; if(unit>1) blocks/=unit; return fs.f_bsize * blocks; /* statfs is also used under FreeBSD (Though it *supports* statvfs() now too) */ #elif defined(__GLIBC__) || defined(BSD) struct statfs fs; unsigned long blocks; if (statfs(path, &fs) < 0) return 0; if(freespace) blocks=fs.f_bavail; else blocks=fs.f_blocks; if(unit>1) blocks/=unit; return fs.f_bsize * blocks; #else fprintf(stderr,"\n*** !Missing getfreediskspace implementation ***\n"); return(0); #endif }
/* * SetupReadWriteTransferPacket * * This function is called once to set up the first attempt to send a packet. * It is not called before a retry, as SRB fields may be modified for the retry. * * Set up the Srb of the TRANSFER_PACKET for the transfer. * The Irp is set up in SubmitTransferPacket because it must be reset * for each packet submission. */ VOID SetupReadWriteTransferPacket( PTRANSFER_PACKET Pkt, PVOID Buf, ULONG Len, LARGE_INTEGER DiskLocation, PIRP OriginalIrp) { PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension; PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData; PIO_STACK_LOCATION origCurSp = IoGetCurrentIrpStackLocation(OriginalIrp); UCHAR majorFunc = origCurSp->MajorFunction; ULONG logicalBlockAddr; ULONG numTransferBlocks; PCDB pCdb; logicalBlockAddr = (ULONG)Int64ShrlMod32(DiskLocation.QuadPart, fdoExt->SectorShift); numTransferBlocks = Len >> fdoExt->SectorShift; /* * Slap the constant SRB fields in from our pre-initialized template. * We'll then only have to fill in the unique fields for this transfer. * Tell lower drivers to sort the SRBs by the logical block address * so that disk seeks are minimized. */ Pkt->Srb = fdoData->SrbTemplate; // copies _contents_ of SRB blocks Pkt->Srb.DataBuffer = Buf; Pkt->Srb.DataTransferLength = Len; Pkt->Srb.QueueSortKey = logicalBlockAddr; Pkt->Srb.OriginalRequest = Pkt->Irp; Pkt->Srb.SenseInfoBuffer = &Pkt->SrbErrorSenseData; Pkt->Srb.TimeOutValue = (Len/0x10000) + ((Len%0x10000) ? 1 : 0); Pkt->Srb.TimeOutValue *= fdoExt->TimeOutValue; /* * Arrange values in CDB in big-endian format. */ pCdb = (PCDB)Pkt->Srb.Cdb; pCdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte3; pCdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte2; pCdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte1; pCdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte0; pCdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte1; pCdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte0; pCdb->CDB10.OperationCode = (majorFunc==IRP_MJ_READ) ? SCSIOP_READ : SCSIOP_WRITE; /* * Set SRB and IRP flags */ Pkt->Srb.SrbFlags = fdoExt->SrbFlags; if (TEST_FLAG(OriginalIrp->Flags, IRP_PAGING_IO) || TEST_FLAG(OriginalIrp->Flags, IRP_SYNCHRONOUS_PAGING_IO)){ SET_FLAG(Pkt->Srb.SrbFlags, SRB_CLASS_FLAGS_PAGING); } SET_FLAG(Pkt->Srb.SrbFlags, (majorFunc==IRP_MJ_READ) ? SRB_FLAGS_DATA_IN : SRB_FLAGS_DATA_OUT); /* * Allow caching only if this is not a write-through request. * If write-through and caching is enabled on the device, force * media access. */ if (TEST_FLAG(origCurSp->Flags, SL_WRITE_THROUGH)){ if (TEST_FLAG(fdoExt->DeviceFlags, DEV_WRITE_CACHE)){ pCdb->CDB10.ForceUnitAccess = TRUE; } } else { SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_ADAPTER_CACHE_ENABLE); } /* * Remember the buf and len in the SRB because miniports * can overwrite SRB.DataTransferLength and we may need it again * for the retry. */ Pkt->BufPtrCopy = Buf; Pkt->BufLenCopy = Len; Pkt->TargetLocationCopy = DiskLocation; Pkt->OriginalIrp = OriginalIrp; Pkt->NumRetries = MAXIMUM_RETRIES; Pkt->SyncEventPtr = NULL; Pkt->CompleteOriginalIrpWhenLastPacketCompletes = TRUE; }
static INT_PTR CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { static int dontsetdefstyle; page *thispage = g_this_page; TCHAR *dir = g_usrvars[thispage->parms[4]]; int browse_text = thispage->parms[3]; if (uMsg == WM_NOTIFY_INIGO_MONTOYA) { GetUIText(IDC_DIR,dir); validate_filename(dir); #ifdef NSIS_CONFIG_LOG #if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT) build_g_logfile(); #endif if (GetUIItem(IDC_CHECK1) != NULL) log_dolog = IsDlgButtonChecked(hwndDlg,IDC_CHECK1); #endif } if (uMsg == WM_INITDIALOG) { HWND hDir = GetUIItem(IDC_DIR); #ifdef NSIS_CONFIG_LOG if (GetAsyncKeyState(VK_SHIFT)&0x8000) { HWND h=GetUIItem(IDC_CHECK1); SetUITextFromLang(IDC_CHECK1,LANG_LOG_INSTALL_PROCESS); ShowWindow(h,SW_SHOWNA); } #endif if (validpathspec(dir) && !skip_root(dir)) addtrailingslash(dir); // workaround for bug #1209843 // // m_curwnd is only updated once WM_INITDIALOG returns. // my_SetWindowText triggers an EN_CHANGE message that // triggers a WM_IN_UPDATEMSG message that uses m_curwnd // to get the selected directory (GetUIText). // because m_curwnd is still outdated, dir varialble is // filled with an empty string. by default, dir points // to $INSTDIR. // // to solve this, m_curwnd is manually set to the correct // window handle. m_curwnd=hwndDlg; my_SetWindowText(hDir,dir); SetUITextFromLang(IDC_BROWSE,this_page->parms[2]); SetUITextFromLang(IDC_SELDIRTEXT,this_page->parms[1]); SetActiveCtl(hDir); { typedef HRESULT (WINAPI *SHAutoCompletePtr)(HWND, DWORD); SHAutoCompletePtr fSHAutoComplete; fSHAutoComplete = (SHAutoCompletePtr) myGetProcAddress(MGA_SHAutoComplete); if (fSHAutoComplete) { fSHAutoComplete(hDir, SHACF_FILESYSTEM); } } } if (uMsg == WM_COMMAND) { int id=LOWORD(wParam); if (id == IDC_DIR && HIWORD(wParam) == EN_CHANGE) { uMsg = WM_IN_UPDATEMSG; } if (id == IDC_BROWSE) { static TCHAR bt[NSIS_MAX_STRLEN]; BROWSEINFO bi = {0,}; ITEMIDLIST *idlist; bi.hwndOwner = hwndDlg; bi.pszDisplayName = g_tmp; bi.lpfn = BrowseCallbackProc; bi.lParam = (LPARAM)dir; bi.lpszTitle = GetNSISString(bt, browse_text); bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; idlist = SHBrowseForFolder(&bi); if (idlist) { // free idlist CoTaskMemFree(idlist); addtrailingslash(dir); if (g_header->install_directory_auto_append && dir == state_install_directory) // only append to $INSTDIR (bug #1174184) { const TCHAR *post_str = ps_tmpbuf; GetNSISStringTT(g_header->install_directory_auto_append); // display name gives just the folder name if (lstrcmpi(post_str, g_tmp)) { mystrcat(dir, post_str); } } dontsetdefstyle++; SetUITextNT(IDC_DIR,dir); } else { uMsg = WM_IN_UPDATEMSG; } } } if (uMsg == WM_IN_UPDATEMSG || uMsg == WM_NOTIFY_START) { static TCHAR s[NSIS_MAX_STRLEN]; int error = 0; int available_set = 0; unsigned total, available; GetUIText(IDC_DIR,dir); if (!is_valid_instpath(dir)) error = NSIS_INSTDIR_INVALID; /** * This part is tricky. We need to make sure a few things: * * 1. GetDiskFreeSpaceEx is always called at least once for large HD. * Even if skip_root() returned NULL (e.g. "C:"). * Note that trimslashtoend() will nullify "C:". * 2. GetDiskFreeSpaceEx is called with the deepest valid directory. * e.g. C:\drive when the user types C:\drive\folder1\folder2. * This makes sure NTFS mount points are treated properly (#1946112). * 3. `s' stays valid after the loop for GetDiskFreeSpace. * This means there is no cutting beyond what skip_root() returns. * Or `s' could be recreated when GetDiskFreeSpace is called. * 4. If GetDiskFreeSpaceEx doesn't exist, GetDiskFreeSpace is used. * 5. Both functions require a trailing backslash * 6. `dir' is never modified. * */ mystrcpy(s,dir); // Test for and use the GetDiskFreeSpaceEx API { BOOL (WINAPI *GDFSE)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER) = myGetProcAddress(MGA_GetDiskFreeSpaceEx); if (GDFSE) { ULARGE_INTEGER available64; ULARGE_INTEGER a, b; TCHAR *p; TCHAR *pw = NULL; while (pw != s) // trimslashtoend() cut the entire string { if (GDFSE(s, &available64, &a, &b)) { #ifndef _NSIS_NO_INT64_SHR available = (int)(available64.QuadPart >> 10); #else available = (int)(Int64ShrlMod32(available64.QuadPart, 10)); #endif available_set++; break; } if (pw) // if pw was set, remove the backslash so trimslashtoend() will cut a new one *pw = 0; p = trimslashtoend(s); // trim last backslash // bring it back, but make the next char null pw = p; *pw = 0; --pw; *pw = _T('\\'); } } } if (!available_set) { DWORD spc, bps, fc, tc; TCHAR *root; // GetDiskFreeSpaceEx accepts any path, but GetDiskFreeSpace accepts only the root mystrcpy(s,dir); root=skip_root(s); if (root) *root=0; // GetDiskFreeSpaceEx is not available if (GetDiskFreeSpace(s, &spc, &bps, &fc, &tc)) { available = (int)MulDiv(bps * spc, fc, 1 << 10); available_set++; } } total = (unsigned) sumsecsfield(size_kb); #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" // available_set is checked first so available is initialized #endif if (available_set && available < total) error = NSIS_INSTDIR_NOT_ENOUGH_SPACE; #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) #pragma GCC diagnostic pop #endif if (LANG_STR_TAB(LANG_SPACE_REQ)) { SetSizeText(IDC_SPACEREQUIRED,LANG_SPACE_REQ,total); if (available_set) SetSizeText(IDC_SPACEAVAILABLE,LANG_SPACE_AVAIL,available); else SetUITextNT(IDC_SPACEAVAILABLE,_T("")); } g_exec_flags.instdir_error = error; #ifdef NSIS_SUPPORT_CODECALLBACKS if (!error) error = ExecuteCallbackFunction(CB_ONVERIFYINSTDIR); #endif if (thispage->flags & PF_DIR_NO_BTN_DISABLE) error = 0; EnableNext(!error); if (!error && !dontsetdefstyle) SetNextDef(); dontsetdefstyle = 0; }
VOID NTAPI ClasspBuildRequestEx( IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PIRP Irp, IN PSCSI_REQUEST_BLOCK Srb ) /*++ ClasspBuildRequestEx() Routine Description: This routine allocates and builds an Srb for a read or write request. The block address and length are supplied by the Irp. The retry count is stored in the current stack for use by ClassIoComplete which processes these requests when they complete. The Irp is ready to be passed to the port driver when this routine returns. Arguments: FdoExtension - Supplies the device extension associated with this request. Irp - Supplies the request to be issued. Srb - Supplies an SRB to be used for the request. Note: If the IRP is for a disk transfer, the byteoffset field will already have been adjusted to make it relative to the beginning of the disk. Return Value: NT Status --*/ { PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset; PCDB cdb; ULONG logicalBlockAddress; USHORT transferBlocks; // This function is obsolete, but still called by CDROM.SYS . // DBGWARN(("ClasspBuildRequestEx is OBSOLETE !")); // // Prepare the SRB. // RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK)); // // Calculate relative sector address. // logicalBlockAddress = (ULONG)(Int64ShrlMod32(startingOffset.QuadPart, FdoExtension->SectorShift)); // // Write length to SRB. // Srb->Length = sizeof(SCSI_REQUEST_BLOCK); // // Set up IRP Address. // Srb->OriginalRequest = Irp; // // Set up target ID and logical unit number. // Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; Srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); // // Save byte count of transfer in SRB Extension. // Srb->DataTransferLength = currentIrpStack->Parameters.Read.Length; // // Initialize the queue actions field. // Srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; // // Queue sort key is Relative Block Address. // Srb->QueueSortKey = logicalBlockAddress; // // Indicate auto request sense by specifying buffer and size. // Srb->SenseInfoBuffer = FdoExtension->SenseData; Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; // // Set timeout value of one unit per 64k bytes of data. // Srb->TimeOutValue = ((Srb->DataTransferLength + 0xFFFF) >> 16) * FdoExtension->TimeOutValue; // // Zero statuses. // Srb->SrbStatus = Srb->ScsiStatus = 0; Srb->NextSrb = 0; // // Indicate that 10-byte CDB's will be used. // Srb->CdbLength = 10; // // Fill in CDB fields. // cdb = (PCDB)Srb->Cdb; transferBlocks = (USHORT)(currentIrpStack->Parameters.Read.Length >> FdoExtension->SectorShift); // // Move little endian values into CDB in big endian format. // cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte3; cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte2; cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte1; cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte0; cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&transferBlocks)->Byte1; cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&transferBlocks)->Byte0; // // Set transfer direction flag and Cdb command. // if (currentIrpStack->MajorFunction == IRP_MJ_READ) { DebugPrint((3, "ClassBuildRequest: Read Command\n")); SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DATA_IN); cdb->CDB10.OperationCode = SCSIOP_READ; } else { DebugPrint((3, "ClassBuildRequest: Write Command\n")); SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DATA_OUT); cdb->CDB10.OperationCode = SCSIOP_WRITE; } // // If this is not a write-through request, then allow caching. // if (!(currentIrpStack->Flags & SL_WRITE_THROUGH)) { SET_FLAG(Srb->SrbFlags, SRB_FLAGS_ADAPTER_CACHE_ENABLE); } else { // // If write caching is enable then force media access in the // cdb. // if (FdoExtension->DeviceFlags & DEV_WRITE_CACHE) { cdb->CDB10.ForceUnitAccess = TRUE; } } if(TEST_FLAG(Irp->Flags, (IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO))) { SET_FLAG(Srb->SrbFlags, SRB_CLASS_FLAGS_PAGING); } // // OR in the default flags from the device object. // SET_FLAG(Srb->SrbFlags, FdoExtension->SrbFlags); // // Set up major SCSI function. // nextIrpStack->MajorFunction = IRP_MJ_SCSI; // // Save SRB address in next stack for port driver. // nextIrpStack->Parameters.Scsi.Srb = Srb; // // Save retry count in current IRP stack. // currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES; // // Set up IoCompletion routine address. // IoSetCompletionRoutine(Irp, ClassIoComplete, Srb, TRUE, TRUE, TRUE); }
static INT_PTR CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { static int dontsetdefstyle; page *thispage = g_this_page; TCHAR *dir = g_usrvars[thispage->parms[4]]; int browse_text = thispage->parms[3]; if (uMsg == WM_NOTIFY_INIGO_MONTOYA) { GetUIText(IDC_DIR,dir); validate_filename(dir); #ifdef NSIS_CONFIG_LOG #if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT) build_g_logfile(); #endif if (GetUIItem(IDC_CHECK1) != NULL) log_dolog = IsDlgButtonChecked(hwndDlg,IDC_CHECK1); #endif } if (uMsg == WM_INITDIALOG) { HWND hDir = GetUIItem(IDC_DIR); #ifdef NSIS_CONFIG_LOG if (GetAsyncKeyState(VK_SHIFT)&0x8000) { HWND h=GetUIItem(IDC_CHECK1); SetUITextFromLang(IDC_CHECK1,LANG_LOG_INSTALL_PROCESS); ShowWindow(h,SW_SHOWNA); } #endif if (validpathspec(dir) && !skip_root(dir)) addtrailingslash(dir); // workaround for bug #1209843 // // m_curwnd is only updated once WM_INITDIALOG returns. // my_SetWindowText triggers an EN_CHANGE message that // triggers a WM_IN_UPDATEMSG message that uses m_curwnd // to get the selected directory (GetUIText). // because m_curwnd is still outdated, dir varialble is // filled with an empty string. by default, dir points // to $INSTDIR. // // to solve this, m_curwnd is manually set to the correct // window handle. m_curwnd=hwndDlg; my_SetWindowText(hDir,dir); SetUITextFromLang(IDC_BROWSE,this_page->parms[2]); SetUITextFromLang(IDC_SELDIRTEXT,this_page->parms[1]); SetActiveCtl(hDir); { typedef HRESULT (WINAPI *SHAutoCompletePtr)(HWND, DWORD); SHAutoCompletePtr fSHAutoComplete; static const TCHAR shlwapi[] = TEXT("shlwapi.dll"); static const char shac[] = "SHAutoComplete"; fSHAutoComplete = (SHAutoCompletePtr) myGetProcAddress((TCHAR *)shlwapi, (char *) shac); if (fSHAutoComplete) { fSHAutoComplete(hDir, SHACF_FILESYSTEM); } } } if (uMsg == WM_COMMAND) { int id=LOWORD(wParam); if (id == IDC_DIR && HIWORD(wParam) == EN_CHANGE) { uMsg = WM_IN_UPDATEMSG; } if (id == IDC_BROWSE) { static TCHAR bt[NSIS_MAX_STRLEN]; BROWSEINFO bi = {0,}; ITEMIDLIST *idlist; bi.hwndOwner = hwndDlg; bi.pszDisplayName = g_tmp; bi.lpfn = BrowseCallbackProc; bi.lParam = (LPARAM)dir; bi.lpszTitle = GetNSISString(bt, browse_text); bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; idlist = SHBrowseForFolder(&bi); if (idlist) { // free idlist FreePIDL(idlist); addtrailingslash(dir); if (g_header->install_directory_auto_append && dir == state_install_directory) // only append to $INSTDIR (bug #1174184) { const TCHAR *post_str = ps_tmpbuf; GetNSISStringTT(g_header->install_directory_auto_append); // display name gives just the folder name if (lstrcmpi(post_str, g_tmp)) { mystrcat(dir, post_str); } } dontsetdefstyle++; SetUITextNT(IDC_DIR,dir); } else { uMsg = WM_IN_UPDATEMSG; } } } if (uMsg == WM_IN_UPDATEMSG || uMsg == WM_NOTIFY_START) { static TCHAR s[NSIS_MAX_STRLEN]; TCHAR *p; int error = 0; int available_set = 0; unsigned total, available = 0xFFFFFFFF; GetUIText(IDC_DIR,dir); if (!is_valid_instpath(dir)) error = NSIS_INSTDIR_INVALID; mystrcpy(s,dir); p=skip_root(s); if (p) *p=0; // Test for and use the GetDiskFreeSpaceEx API { #ifdef UNICODE BOOL (WINAPI *GDFSE)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER) = myGetProcAddress(L"KERNEL32.dll", "GetDiskFreeSpaceExW"); #else BOOL (WINAPI *GDFSE)(LPCSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER) = myGetProcAddress("KERNEL32.dll", "GetDiskFreeSpaceExA"); #endif if (GDFSE) { ULARGE_INTEGER available64; ULARGE_INTEGER a, b; if (GDFSE(s, &available64, &a, &b)) { #ifndef _NSIS_NO_INT64_SHR available = (int)(available64.QuadPart >> 10); #else available = (int)(Int64ShrlMod32(available64.QuadPart, 10)); #endif available_set++; } } } if (!available_set) { // GetDiskFreeSpaceEx is not available DWORD spc, bps, fc, tc; if (GetDiskFreeSpace(s, &spc, &bps, &fc, &tc)) { available = (int)MulDiv(bps * spc, fc, 1 << 10); available_set++; } } total = (unsigned) sumsecsfield(size_kb); if (available < total) error = NSIS_INSTDIR_NOT_ENOUGH_SPACE; if (LANG_STR_TAB(LANG_SPACE_REQ)) { SetSizeText(IDC_SPACEREQUIRED,LANG_SPACE_REQ,total); if (available_set) SetSizeText(IDC_SPACEAVAILABLE,LANG_SPACE_AVAIL,available); else SetUITextNT(IDC_SPACEAVAILABLE,TEXT("")); } g_exec_flags.instdir_error = error; #ifdef NSIS_SUPPORT_CODECALLBACKS if (!error) error = ExecuteCallbackFunction(CB_ONVERIFYINSTDIR); #endif if (thispage->flags & PF_DIR_NO_BTN_DISABLE) error = 0; EnableNext(!error); if (!error && !dontsetdefstyle) SetNextDef(); dontsetdefstyle = 0; }
/* * SetupReadWriteTransferPacket * * This function is called once to set up the first attempt to send a packet. * It is not called before a retry, as SRB fields may be modified for the retry. * * Set up the Srb of the TRANSFER_PACKET for the transfer. * The Irp is set up in SubmitTransferPacket because it must be reset * for each packet submission. */ VOID SetupReadWriteTransferPacket( PTRANSFER_PACKET Pkt, PVOID Buf, ULONG Len, LARGE_INTEGER DiskLocation, PIRP OriginalIrp) { PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension; PCOMMON_DEVICE_EXTENSION commonExtension = Pkt->Fdo->DeviceExtension; PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData; PIO_STACK_LOCATION origCurSp = IoGetCurrentIrpStackLocation(OriginalIrp); UCHAR majorFunc = origCurSp->MajorFunction; LARGE_INTEGER logicalBlockAddr; ULONG numTransferBlocks; PCDB pCdb; logicalBlockAddr.QuadPart = Int64ShrlMod32(DiskLocation.QuadPart, fdoExt->SectorShift); numTransferBlocks = Len >> fdoExt->SectorShift; /* * This field is useful when debugging, since low-memory conditions are * handled differently for CDROM (which is the only driver using StartIO) */ Pkt->DriverUsesStartIO = (commonExtension->DriverExtension->InitData.ClassStartIo != NULL); /* * Slap the constant SRB fields in from our pre-initialized template. * We'll then only have to fill in the unique fields for this transfer. * Tell lower drivers to sort the SRBs by the logical block address * so that disk seeks are minimized. */ Pkt->Srb = fdoData->SrbTemplate; // copies _contents_ of SRB blocks Pkt->Srb.DataBuffer = Buf; Pkt->Srb.DataTransferLength = Len; Pkt->Srb.QueueSortKey = logicalBlockAddr.LowPart; if (logicalBlockAddr.QuadPart > 0xFFFFFFFF) { // // If the requested LBA is more than max ULONG set the // QueueSortKey to the maximum value, so that these // requests can be added towards the end of the queue. // Pkt->Srb.QueueSortKey = 0xFFFFFFFF; } Pkt->Srb.OriginalRequest = Pkt->Irp; Pkt->Srb.SenseInfoBuffer = &Pkt->SrbErrorSenseData; // // Temporarily disable timeout calculation based on transfer size due to // the large default timeout value. // Pkt->Srb.TimeOutValue = fdoExt->TimeOutValue; // Pkt->Srb.TimeOutValue = (Len/0x10000) + ((Len%0x10000) ? 1 : 0); // Pkt->Srb.TimeOutValue *= fdoExt->TimeOutValue; /* * Arrange values in CDB in big-endian format. */ pCdb = (PCDB)Pkt->Srb.Cdb; if (TEST_FLAG(fdoExt->DeviceFlags, DEV_USE_16BYTE_CDB)) { REVERSE_BYTES_QUAD(&pCdb->CDB16.LogicalBlock, &logicalBlockAddr); REVERSE_BYTES(&pCdb->CDB16.TransferLength, &numTransferBlocks); pCdb->CDB16.OperationCode = (majorFunc==IRP_MJ_READ) ? SCSIOP_READ16 : SCSIOP_WRITE16; Pkt->Srb.CdbLength = 16; } else { pCdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte3; pCdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte2; pCdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte1; pCdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte0; pCdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte1; pCdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte0; pCdb->CDB10.OperationCode = (majorFunc==IRP_MJ_READ) ? SCSIOP_READ : SCSIOP_WRITE; } /* * Set SRB and IRP flags */ Pkt->Srb.SrbFlags = fdoExt->SrbFlags; if (TEST_FLAG(OriginalIrp->Flags, IRP_PAGING_IO) || TEST_FLAG(OriginalIrp->Flags, IRP_SYNCHRONOUS_PAGING_IO)){ SET_FLAG(Pkt->Srb.SrbFlags, SRB_CLASS_FLAGS_PAGING); } SET_FLAG(Pkt->Srb.SrbFlags, (majorFunc==IRP_MJ_READ) ? SRB_FLAGS_DATA_IN : SRB_FLAGS_DATA_OUT); /* * Allow caching only if this is not a write-through request. * If write-through and caching is enabled on the device, force * media access. * Ignore SL_WRITE_THROUGH for reads; it's only set because the file handle was opened with WRITE_THROUGH. */ if ((majorFunc == IRP_MJ_WRITE) && TEST_FLAG(origCurSp->Flags, SL_WRITE_THROUGH)) { pCdb->CDB10.ForceUnitAccess = fdoExt->CdbForceUnitAccess; } else { SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_ADAPTER_CACHE_ENABLE); } /* * Remember the buf and len in the SRB because miniports * can overwrite SRB.DataTransferLength and we may need it again * for the retry. */ Pkt->BufPtrCopy = Buf; Pkt->BufLenCopy = Len; Pkt->TargetLocationCopy = DiskLocation; Pkt->OriginalIrp = OriginalIrp; Pkt->NumRetries = NUM_IO_RETRIES; Pkt->SyncEventPtr = NULL; Pkt->CompleteOriginalIrpWhenLastPacketCompletes = TRUE; DBGLOGFLUSHINFO(fdoData, TRUE, (BOOLEAN)(pCdb->CDB10.ForceUnitAccess), FALSE); }