Ejemplo n.º 1
0
static void __cdecl FormatWriteThreadProc (void *arg)
{
	DWORD bytesWritten;

	SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_HIGHEST);

	while (!WriteThreadExitRequested)
	{
		if (WaitForSingleObject (WriteBufferFullEvent, INFINITE) == WAIT_FAILED)
		{
			handleWin32Error (NULL, SRC_POS);
			break;
		}

		if (WriteThreadExitRequested)
			break;

		if (!WriteFile (WriteRequestHandle, WriteThreadBuffer, WriteRequestSize, &bytesWritten, NULL))
			WriteRequestResult = GetLastError();
		else		
			WriteRequestResult = ERROR_SUCCESS;

		if (!SetEvent (WriteBufferEmptyEvent))
		{
			handleWin32Error (NULL, SRC_POS);
			break;
		}
	}

	WriteThreadRunning = FALSE;
	_endthread();
}
Ejemplo n.º 2
0
/* Init the random number generator, setup the hooks, and start the thread */
int Randinit ()
{
	DWORD dwLastError = ERROR_SUCCESS;
	if (GetMaxPkcs5OutSize() > RNG_POOL_SIZE)
		TC_THROW_FATAL_EXCEPTION;

	if(bRandDidInit) 
		return 0;

	InitializeCriticalSection (&critRandProt);

	bRandDidInit = TRUE;
	CryptoAPILastError = ERROR_SUCCESS;
	ProcessedMouseEventsCounter = 0;

	if (pRandPool == NULL)
	{
		pRandPool = (unsigned char *) TCalloc (RANDOMPOOL_ALLOCSIZE);
		if (pRandPool == NULL)
			goto error;

		bDidSlowPoll = FALSE;
		RandomPoolEnrichedByUser = FALSE;

		memset (pRandPool, 0, RANDOMPOOL_ALLOCSIZE);
		VirtualLock (pRandPool, RANDOMPOOL_ALLOCSIZE);
	}

	hKeyboard = SetWindowsHookEx (WH_KEYBOARD, (HOOKPROC)&KeyboardProc, NULL, GetCurrentThreadId ());
	if (hKeyboard == 0) handleWin32Error (0, SRC_POS);

	hMouse = SetWindowsHookEx (WH_MOUSE, (HOOKPROC)&MouseProc, NULL, GetCurrentThreadId ());
	if (hMouse == 0)
	{
		handleWin32Error (0, SRC_POS);
		goto error;
	}
	
	if (!CryptAcquireContext (&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
	{		
		CryptoAPIAvailable = FALSE;
		CryptoAPILastError = GetLastError ();
		goto error;
	}
	else
		CryptoAPIAvailable = TRUE;

	if (!(PeriodicFastPollThreadHandle = (HANDLE) _beginthreadex (NULL, 0, PeriodicFastPollThreadProc, NULL, 0, NULL)))
		goto error;

	return 0;

error:
	dwLastError = GetLastError();
	RandStop (TRUE);
	SetLastError (dwLastError);
	return 1;
}
Ejemplo n.º 3
0
/* Init the random number generator, setup the hooks, and start the thread */
int Randinit ()
{
	if (GetMaxPkcs5OutSize() > RNG_POOL_SIZE)
		TC_THROW_FATAL_EXCEPTION;

	if(bRandDidInit) 
		return 0;

	InitializeCriticalSection (&critRandProt);

	bRandDidInit = TRUE;

	if (pRandPool == NULL)
	{
		pRandPool = (unsigned char *) TCalloc (RANDOMPOOL_ALLOCSIZE);
		if (pRandPool == NULL)
			goto error;

		bDidSlowPoll = FALSE;
		RandomPoolEnrichedByUser = FALSE;

		memset (pRandPool, 0, RANDOMPOOL_ALLOCSIZE);
		VirtualLock (pRandPool, RANDOMPOOL_ALLOCSIZE);
	}

	hKeyboard = SetWindowsHookEx (WH_KEYBOARD, (HOOKPROC)&KeyboardProc, NULL, GetCurrentThreadId ());
	if (hKeyboard == 0) handleWin32Error (0);

	hMouse = SetWindowsHookEx (WH_MOUSE, (HOOKPROC)&MouseProc, NULL, GetCurrentThreadId ());
	if (hMouse == 0)
	{
		handleWin32Error (0);
		goto error;
	}

	if (!CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)
		&& !CryptAcquireContext (&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
		CryptoAPIAvailable = FALSE;
	else
		CryptoAPIAvailable = TRUE;

	if (!(PeriodicFastPollThreadHandle = (HANDLE) _beginthreadex (NULL, 0, PeriodicFastPollThreadProc, NULL, 0, NULL)))
		goto error;

	return 0;

error:
	RandStop (TRUE);
	return 1;
}
Ejemplo n.º 4
0
int Win32CommandLine (char *lpszCommandLine, char ***lpszArgs)
{
	int argumentCount;
	int i;

	LPWSTR *arguments = CommandLineToArgvW (GetCommandLineW(), &argumentCount);
	if (!arguments)
	{
		handleWin32Error (NULL);
		return 0;
	}

	--argumentCount;
	if (argumentCount < 1)
	{
		LocalFree (arguments);
		return 0;
	}

	*lpszArgs = malloc (sizeof (char *) * argumentCount);
	if (!*lpszArgs)
		AbortProcess ("OUTOFMEMORY");

	for (i = 0; i < argumentCount; ++i)
	{
		size_t argLen = wcslen (arguments[i + 1]);

		char *arg = malloc (argLen + 1);
		if (!arg)
			AbortProcess ("OUTOFMEMORY");

		if (argLen > 0)
		{
			int len = WideCharToMultiByte (CP_ACP, 0, arguments[i + 1], -1, arg, argLen + 1, NULL, NULL);
			if (len == 0)
			{
				handleWin32Error (NULL);
				AbortProcessSilent();
			}
		}
		else
			arg[0] = 0;

		(*lpszArgs)[i] = arg;
	}

	LocalFree (arguments);
	return argumentCount;
}
Ejemplo n.º 5
0
int TCFormatVolume (volatile FORMAT_VOL_PARAMETERS *volParams)
{
	int nStatus;
	PCRYPTO_INFO cryptoInfo = NULL;
	HANDLE dev = INVALID_HANDLE_VALUE;
	DWORD dwError;
	char header[TC_VOLUME_HEADER_EFFECTIVE_SIZE];
	unsigned __int64 num_sectors, startSector;
	fatparams ft;
	FILETIME ftCreationTime;
	FILETIME ftLastWriteTime;
	FILETIME ftLastAccessTime;
	BOOL bTimeStampValid = FALSE;
	BOOL bInstantRetryOtherFilesys = FALSE;
	char dosDev[TC_MAX_PATH] = { 0 };
	char devName[MAX_PATH] = { 0 };
	int driveLetter = -1;
	WCHAR deviceName[MAX_PATH];
	uint64 dataOffset, dataAreaSize;
	LARGE_INTEGER offset;
	BOOL bFailedRequiredDASD = FALSE;
	HWND hwndDlg = volParams->hwndDlg;

	FormatSectorSize = volParams->sectorSize;

	if (FormatSectorSize < TC_MIN_VOLUME_SECTOR_SIZE
		|| FormatSectorSize > TC_MAX_VOLUME_SECTOR_SIZE
		|| FormatSectorSize % ENCRYPTION_DATA_UNIT_SIZE != 0)
	{
		Error ("SECTOR_SIZE_UNSUPPORTED", hwndDlg);
		return ERR_DONT_REPORT; 
	}

	/* WARNING: Note that if Windows fails to format the volume as NTFS and the volume size is
	less than the maximum FAT size, the user is asked within this function whether he wants to instantly
	retry FAT format instead (to avoid having to re-create the whole container again). If the user
	answers yes, some of the input parameters are modified, the code below 'begin_format' is re-executed 
	and some destructive operations that were performed during the first attempt must be (and are) skipped. 
	Therefore, whenever adding or modifying any potentially destructive operations below 'begin_format',
	determine whether they (or their portions) need to be skipped during such a second attempt; if so, 
	use the 'bInstantRetryOtherFilesys' flag to skip them. */

	if (volParams->hiddenVol)
	{
		dataOffset = volParams->hiddenVolHostSize - TC_VOLUME_HEADER_GROUP_SIZE - volParams->size;
	}
	else
	{
		if (volParams->size <= TC_TOTAL_VOLUME_HEADERS_SIZE)
			return ERR_VOL_SIZE_WRONG;

		dataOffset = TC_VOLUME_DATA_OFFSET;
	}

	dataAreaSize = GetVolumeDataAreaSize (volParams->hiddenVol, volParams->size);

	num_sectors = dataAreaSize / FormatSectorSize;

	if (volParams->bDevice)
	{
		StringCbCopyA ((char *)deviceName, sizeof(deviceName), volParams->volumePath);
		ToUNICODE ((char *)deviceName, sizeof(deviceName));

		driveLetter = GetDiskDeviceDriveLetter (deviceName);
	}

	VirtualLock (header, sizeof (header));

	nStatus = CreateVolumeHeaderInMemory (hwndDlg, FALSE,
				     header,
				     volParams->ea,
					 FIRST_MODE_OF_OPERATION_ID,
				     volParams->password,
				     volParams->pkcs5,
					  volParams->pim,
					 NULL,
				     &cryptoInfo,
					 dataAreaSize,
					 volParams->hiddenVol ? dataAreaSize : 0,
					 dataOffset,
					 dataAreaSize,
					 0,
					 volParams->headerFlags,
					 FormatSectorSize,
					 FALSE);

	if (nStatus != 0)
	{
		burn (header, sizeof (header));
		VirtualUnlock (header, sizeof (header));
		return nStatus;
	}

begin_format:

	if (volParams->bDevice)
	{
		/* Device-hosted volume */

		DWORD dwResult;
		int nPass;

		if (FakeDosNameForDevice (volParams->volumePath, dosDev, sizeof(dosDev), devName, sizeof(devName), FALSE) != 0)
			return ERR_OS_ERROR;

		if (IsDeviceMounted (devName))
		{
			if ((dev = DismountDrive (devName, volParams->volumePath)) == INVALID_HANDLE_VALUE)
			{
				Error ("FORMAT_CANT_DISMOUNT_FILESYS", hwndDlg);
				nStatus = ERR_DONT_REPORT; 
				goto error;
			}

			/* Gain "raw" access to the partition (it contains a live filesystem and the filesystem driver 
			would otherwise prevent us from writing to hidden sectors). */

			if (!DeviceIoControl (dev,
				FSCTL_ALLOW_EXTENDED_DASD_IO,
				NULL,
				0,   
				NULL,
				0,
				&dwResult,
				NULL))
			{
				bFailedRequiredDASD = TRUE;
			}
		}
		else if (IsOSAtLeast (WIN_VISTA) && driveLetter == -1)
		{
			// Windows Vista doesn't allow overwriting sectors belonging to an unformatted partition 
			// to which no drive letter has been assigned under the system. This problem can be worked
			// around by assigning a drive letter to the partition temporarily.

			char szDriveLetter[] = { 'A', ':', 0 };
			char rootPath[] = { 'A', ':', '\\', 0 };
			char uniqVolName[MAX_PATH+1] = { 0 };
			int tmpDriveLetter = -1;
			BOOL bResult = FALSE;

			tmpDriveLetter = GetFirstAvailableDrive ();
 
			if (tmpDriveLetter != -1)
			{
				rootPath[0] += (char) tmpDriveLetter;
				szDriveLetter[0] += (char) tmpDriveLetter;

				if (DefineDosDevice (DDD_RAW_TARGET_PATH, szDriveLetter, volParams->volumePath))
				{
					bResult = GetVolumeNameForVolumeMountPoint (rootPath, uniqVolName, MAX_PATH);

					DefineDosDevice (DDD_RAW_TARGET_PATH|DDD_REMOVE_DEFINITION|DDD_EXACT_MATCH_ON_REMOVE,
						szDriveLetter,
						volParams->volumePath);

					if (bResult 
						&& SetVolumeMountPoint (rootPath, uniqVolName))
					{
						// The drive letter can be removed now
						DeleteVolumeMountPoint (rootPath);
					}
				}
			}
		}

		// For extra safety, we will try to gain "raw" access to the partition. Note that this should actually be
		// redundant because if the filesystem was mounted, we already tried to obtain DASD above. If we failed,
		// bFailedRequiredDASD was set to TRUE and therefore we will perform pseudo "quick format" below. However, 
		// for extra safety, in case IsDeviceMounted() failed to detect a live filesystem, we will blindly
		// send FSCTL_ALLOW_EXTENDED_DASD_IO (possibly for a second time) without checking the result.

		DeviceIoControl (dev,
			FSCTL_ALLOW_EXTENDED_DASD_IO,
			NULL,
			0,   
			NULL,
			0,
			&dwResult,
			NULL);


		// If DASD is needed but we failed to obtain it, perform open - 'quick format' - close - open 
		// so that the filesystem driver does not prevent us from formatting hidden sectors.
		for (nPass = (bFailedRequiredDASD ? 0 : 1); nPass < 2; nPass++)
		{
			int retryCount;

			retryCount = 0;

			// Try exclusive access mode first
			// Note that when exclusive access is denied, it is worth retrying (usually succeeds after a few tries).
			while (dev == INVALID_HANDLE_VALUE && retryCount++ < EXCL_ACCESS_MAX_AUTO_RETRIES)
			{
				dev = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

				if (retryCount > 1)
					Sleep (EXCL_ACCESS_AUTO_RETRY_DELAY);
			}

			if (dev == INVALID_HANDLE_VALUE)
			{
				// Exclusive access denied -- retry in shared mode
				dev = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
				if (dev != INVALID_HANDLE_VALUE)
				{
					if (!volParams->bForceOperation && (Silent || (IDNO == MessageBoxW (volParams->hwndDlg, GetString ("DEVICE_IN_USE_FORMAT"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2))))
					{
						nStatus = ERR_DONT_REPORT; 
						goto error;
					}
				}
				else
				{
					handleWin32Error (volParams->hwndDlg, SRC_POS);
					Error ("CANT_ACCESS_VOL", hwndDlg);
					nStatus = ERR_DONT_REPORT; 
					goto error;
				}
			}

			if (volParams->hiddenVol || bInstantRetryOtherFilesys)
				break;	// The following "quick format" operation would damage the outer volume

			if (nPass == 0)
			{
				char buf [2 * TC_MAX_VOLUME_SECTOR_SIZE];
				DWORD bw;

				// Perform pseudo "quick format" so that the filesystem driver does not prevent us from 
				// formatting hidden sectors
				memset (buf, 0, sizeof (buf));

				if (!WriteFile (dev, buf, sizeof (buf), &bw, NULL))
				{
					nStatus = ERR_OS_ERROR; 
					goto error;
				}

				FlushFileBuffers (dev);
				CloseHandle (dev);
				dev = INVALID_HANDLE_VALUE;
			}
		}

		if (DeviceIoControl (dev, FSCTL_IS_VOLUME_MOUNTED, NULL, 0, NULL, 0, &dwResult, NULL))
		{
			Error ("FORMAT_CANT_DISMOUNT_FILESYS", hwndDlg);
			nStatus = ERR_DONT_REPORT; 
			goto error;
		}
	}
	else
	{
		/* File-hosted volume */

		dev = CreateFile (volParams->volumePath, GENERIC_READ | GENERIC_WRITE,
			(volParams->hiddenVol || bInstantRetryOtherFilesys) ? (FILE_SHARE_READ | FILE_SHARE_WRITE) : 0,
			NULL, (volParams->hiddenVol || bInstantRetryOtherFilesys) ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL);

		if (dev == INVALID_HANDLE_VALUE)
		{
			nStatus = ERR_OS_ERROR; 
			goto error;
		}

		DisableFileCompression (dev);

		if (!volParams->hiddenVol && !bInstantRetryOtherFilesys)
		{
			LARGE_INTEGER volumeSize;
			volumeSize.QuadPart = dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE;

			if (volParams->sparseFileSwitch && volParams->quickFormat)
			{
				// Create as sparse file container
				DWORD tmp;
				if (!DeviceIoControl (dev, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &tmp, NULL))
				{
					nStatus = ERR_OS_ERROR; 
					goto error;
				}
			}

			// Preallocate the file
			if (!SetFilePointerEx (dev, volumeSize, NULL, FILE_BEGIN)
				|| !SetEndOfFile (dev)
				|| SetFilePointer (dev, 0, NULL, FILE_BEGIN) != 0)
			{
				nStatus = ERR_OS_ERROR;
				goto error;
			}
		}
	}

	if (volParams->hiddenVol && !volParams->bDevice && bPreserveTimestamp)
	{
		if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
			bTimeStampValid = FALSE;
		else
			bTimeStampValid = TRUE;
	}

	if (volParams->hwndDlg && volParams->bGuiMode) KillTimer (volParams->hwndDlg, TIMER_ID_RANDVIEW);

	/* Volume header */

	// Hidden volume setup
	if (volParams->hiddenVol)
	{
		LARGE_INTEGER headerOffset;

		// Check hidden volume size
		if (volParams->hiddenVolHostSize < TC_MIN_HIDDEN_VOLUME_HOST_SIZE || volParams->hiddenVolHostSize > TC_MAX_HIDDEN_VOLUME_HOST_SIZE)
		{		
			nStatus = ERR_VOL_SIZE_WRONG;
			goto error;
		}

		// Seek to hidden volume header location
		
		headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET;

		if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
		{
			nStatus = ERR_OS_ERROR;
			goto error;
		}
	}
	else if (bInstantRetryOtherFilesys)
	{
		// The previous file system format failed and the user wants to try again with a different file system.
		// The volume header had been written successfully so we need to seek to the byte after the header.

		LARGE_INTEGER offset;
		offset.QuadPart = TC_VOLUME_DATA_OFFSET;
		if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN))
		{
			nStatus = ERR_OS_ERROR;
			goto error;
		}
	}

	if (!bInstantRetryOtherFilesys)
	{
		// Write the volume header
		if (!WriteEffectiveVolumeHeader (volParams->bDevice, dev, header))
		{
			nStatus = ERR_OS_ERROR;
			goto error;
		}

		// To prevent fragmentation, write zeroes to reserved header sectors which are going to be filled with random data
		if (!volParams->bDevice && !volParams->hiddenVol)
		{
			byte buf[TC_VOLUME_HEADER_GROUP_SIZE - TC_VOLUME_HEADER_EFFECTIVE_SIZE];
			DWORD bytesWritten;
			ZeroMemory (buf, sizeof (buf));

			if (!WriteFile (dev, buf, sizeof (buf), &bytesWritten, NULL))
			{
				nStatus = ERR_OS_ERROR;
				goto error;
			}

			if (bytesWritten != sizeof (buf))
			{
				nStatus = ERR_PARAMETER_INCORRECT;
				goto error;
			}
		}
	}

	if (volParams->hiddenVol)
	{
		// Calculate data area position of hidden volume
		cryptoInfo->hiddenVolumeOffset = dataOffset;

		// Validate the offset
		if (dataOffset % FormatSectorSize != 0)
		{
			nStatus = ERR_VOL_SIZE_WRONG; 
			goto error;
		}

		volParams->quickFormat = TRUE;		// To entirely format a hidden volume would be redundant
	}

	/* Data area */
	startSector = dataOffset / FormatSectorSize;

	// Format filesystem

	switch (volParams->fileSystem)
	{
	case FILESYS_NONE:
	case FILESYS_NTFS:

		if (volParams->bDevice && !StartFormatWriteThread())
		{
			nStatus = ERR_OS_ERROR; 
			goto error;
		}

		nStatus = FormatNoFs (hwndDlg, startSector, num_sectors, dev, cryptoInfo, volParams->quickFormat);

		if (volParams->bDevice)
			StopFormatWriteThread();

		break;
		
	case FILESYS_FAT:
		if (num_sectors > 0xFFFFffff)
		{
			nStatus = ERR_VOL_SIZE_WRONG; 
			goto error;
		}

		// Calculate the fats, root dir etc
		ft.num_sectors = (unsigned int) (num_sectors);

#if TC_MAX_VOLUME_SECTOR_SIZE > 0xFFFF
#error TC_MAX_VOLUME_SECTOR_SIZE > 0xFFFF
#endif

		ft.sector_size = (uint16) FormatSectorSize;
		ft.cluster_size = volParams->clusterSize;
		memcpy (ft.volume_name, "NO NAME    ", 11);
		GetFatParams (&ft); 
		*(volParams->realClusterSize) = ft.cluster_size * FormatSectorSize;

		if (volParams->bDevice && !StartFormatWriteThread())
		{
			nStatus = ERR_OS_ERROR; 
			goto error;
		}

		nStatus = FormatFat (hwndDlg, startSector, &ft, (void *) dev, cryptoInfo, volParams->quickFormat);

		if (volParams->bDevice)
			StopFormatWriteThread();

		break;

	default:
		nStatus = ERR_PARAMETER_INCORRECT; 
		goto error;
	}

	if (nStatus != ERR_SUCCESS)
		goto error;

	// Write header backup
	offset.QuadPart = volParams->hiddenVol ? volParams->hiddenVolHostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET : dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE;

	if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN))
	{
		nStatus = ERR_OS_ERROR;
		goto error;
	}

	nStatus = CreateVolumeHeaderInMemory (hwndDlg, FALSE,
		header,
		volParams->ea,
		FIRST_MODE_OF_OPERATION_ID,
		volParams->password,
		volParams->pkcs5,
		volParams->pim,
		cryptoInfo->master_keydata,
		&cryptoInfo,
		dataAreaSize,
		volParams->hiddenVol ? dataAreaSize : 0,
		dataOffset,
		dataAreaSize,
		0,
		volParams->headerFlags,
		FormatSectorSize,
		FALSE);

	if (!WriteEffectiveVolumeHeader (volParams->bDevice, dev, header))
	{
		nStatus = ERR_OS_ERROR;
		goto error;
	}

	// Fill reserved header sectors (including the backup header area) with random data
	if (!volParams->hiddenVol)
	{
		nStatus = WriteRandomDataToReservedHeaderAreas (hwndDlg, dev, cryptoInfo, dataAreaSize, FALSE, FALSE);

		if (nStatus != ERR_SUCCESS)
			goto error;
	}

#ifndef DEBUG
	if (volParams->quickFormat && volParams->fileSystem != FILESYS_NTFS)
		Sleep (500);	// User-friendly GUI
#endif

error:
	dwError = GetLastError();

	burn (header, sizeof (header));
	VirtualUnlock (header, sizeof (header));

	if (dev != INVALID_HANDLE_VALUE)
	{
		if (!volParams->bDevice && !volParams->hiddenVol && nStatus != 0)
		{
			// Remove preallocated part before closing file handle if format failed
			if (SetFilePointer (dev, 0, NULL, FILE_BEGIN) == 0)
				SetEndOfFile (dev);
		}

		FlushFileBuffers (dev);

		if (bTimeStampValid)
			SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime);

		CloseHandle (dev);
		dev = INVALID_HANDLE_VALUE;
	}

	if (nStatus != 0)
	{
		SetLastError(dwError);
		goto fv_end;
	}

	if (volParams->fileSystem == FILESYS_NTFS)
	{
		// Quick-format volume as NTFS
		int driveNo = GetLastAvailableDrive ();
		MountOptions mountOptions;
		int retCode;

		ZeroMemory (&mountOptions, sizeof (mountOptions));

		if (driveNo == -1)
		{
			if (!Silent)
			{
				MessageBoxW (volParams->hwndDlg, GetString ("NO_FREE_DRIVES"), lpszTitle, ICON_HAND);
				MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
			}

			nStatus = ERR_NO_FREE_DRIVES;
			goto fv_end;
		}

		mountOptions.ReadOnly = FALSE;
		mountOptions.Removable = FALSE;
		mountOptions.ProtectHiddenVolume = FALSE;
		mountOptions.PreserveTimestamp = bPreserveTimestamp;
		mountOptions.PartitionInInactiveSysEncScope = FALSE;
		mountOptions.UseBackupHeader = FALSE;

		if (MountVolume (volParams->hwndDlg, driveNo, volParams->volumePath, volParams->password, volParams->pkcs5, volParams->pim, FALSE, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1)
		{
			if (!Silent)
			{
				MessageBoxW (volParams->hwndDlg, GetString ("CANT_MOUNT_VOLUME"), lpszTitle, ICON_HAND);
				MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
			}
			nStatus = ERR_VOL_MOUNT_FAILED;
			goto fv_end;
		}

		if (!Silent && !IsAdmin () && IsUacSupported ())
			retCode = UacFormatNtfs (volParams->hwndDlg, driveNo, volParams->clusterSize);
		else
			retCode = FormatNtfs (driveNo, volParams->clusterSize);

		if (retCode != TRUE)
		{
			if (!UnmountVolumeAfterFormatExCall (volParams->hwndDlg, driveNo) && !Silent)
				MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);

			if (dataAreaSize <= TC_MAX_FAT_SECTOR_COUNT * FormatSectorSize)
			{
				if (AskErrYesNo ("FORMAT_NTFS_FAILED_ASK_FAT", hwndDlg) == IDYES)
				{
					// NTFS format failed and the user wants to try FAT format immediately
					volParams->fileSystem = FILESYS_FAT;
					bInstantRetryOtherFilesys = TRUE;
					volParams->quickFormat = TRUE;		// Volume has already been successfully TC-formatted
					volParams->clusterSize = 0;		// Default cluster size
					goto begin_format;
				}
			}
			else
				Error ("FORMAT_NTFS_FAILED", hwndDlg);

			nStatus = ERR_DONT_REPORT;
			goto fv_end;
		}

		if (!UnmountVolumeAfterFormatExCall (volParams->hwndDlg, driveNo) && !Silent)
			MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
	}

fv_end:
	dwError = GetLastError();

	if (dosDev[0])
		RemoveFakeDosName (volParams->volumePath, dosDev);

	crypto_close (cryptoInfo);

	SetLastError (dwError);
	return nStatus;
}
Ejemplo n.º 6
0
void __cdecl ExtractAllFilesThread (void *hwndDlg)
{
	int fileNo;
	BOOL bSuccess = FALSE;
	char packageFile [TC_MAX_PATH];

	InvalidateRect (GetDlgItem (GetParent (hwndDlg), IDD_INSTL_DLG), NULL, TRUE);

	ClearLogWindow (hwndDlg);

	GetModuleFileName (NULL, packageFile, sizeof (packageFile));

	if (!(bSuccess = SelfExtractInMemory (packageFile)))
		goto eaf_end;

	if (mkfulldir (DestExtractPath, TRUE) != 0)
	{
		if (mkfulldir (DestExtractPath, FALSE) != 0)
		{
			wchar_t szTmp[TC_MAX_PATH];

			handleWin32Error (hwndDlg);
			wsprintfW (szTmp, GetString ("CANT_CREATE_FOLDER"), DestExtractPath);
			MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONHAND);
			bSuccess = FALSE;
			goto eaf_end;
		}
	}

	for (fileNo = 0; fileNo < NBR_COMPRESSED_FILES; fileNo++)
	{
		char fileName [TC_MAX_PATH] = {0};
		char filePath [TC_MAX_PATH] = {0};

		// Filename
		strncpy (fileName, Decompressed_Files[fileNo].fileName, Decompressed_Files[fileNo].fileNameLength);
		fileName [Decompressed_Files[fileNo].fileNameLength] = 0;
		strcpy (filePath, DestExtractPath);
		strcat (filePath, fileName);

		StatusMessageParam (hwndDlg, "EXTRACTING_VERB", filePath);

		// Write the file
		if (!SaveBufferToFile (
			Decompressed_Files[fileNo].fileContent,
			filePath,
			Decompressed_Files[fileNo].fileLength,
			FALSE))
		{
			wchar_t szTmp[512];

			_snwprintf (szTmp, sizeof (szTmp) / 2, GetString ("CANNOT_WRITE_FILE_X"), filePath);
			MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST);
			bSuccess = FALSE;
			goto eaf_end;
		}
		UpdateProgressBarProc ((int) (100 * ((float) fileNo / NBR_COMPRESSED_FILES)));
	}

eaf_end:
	FreeAllFileBuffers();

	if (bSuccess)
		PostMessage (MainDlg, TC_APPMSG_EXTRACTION_SUCCESS, 0, 0);
	else
		PostMessage (MainDlg, TC_APPMSG_EXTRACTION_FAILURE, 0, 0);
}
Ejemplo n.º 7
0
BOOL MakeSelfExtractingPackage (HWND hwndDlg, char *szDestDir)
{
	int i, x;
	unsigned char inputFile [TC_MAX_PATH];
	unsigned char outputFile [TC_MAX_PATH];
	unsigned char szTmpFilePath [TC_MAX_PATH];
	unsigned char szTmp32bit [4] = {0};
	unsigned char *szTmp32bitPtr = szTmp32bit;
	unsigned char *buffer = NULL, *compressedBuffer = NULL;
	unsigned char *bufIndex = NULL;
	char tmpStr [2048];
	int bufLen = 0, compressedDataLen = 0, uncompressedDataLen = 0;

	x = strlen (szDestDir);
	if (x < 2)
		return FALSE;

	if (szDestDir[x - 1] != '\\')
		strcat (szDestDir, "\\");

	GetModuleFileName (NULL, inputFile, sizeof (inputFile));

	strcpy (outputFile, szDestDir);
	strncat (outputFile, OutputPackageFile, sizeof (outputFile) - strlen (outputFile) - 1);

	// Clone 'TrueCrypt Setup.exe' to create the base of the new self-extracting archive

	if (!TCCopyFile (inputFile, outputFile))
	{
		handleWin32Error (hwndDlg);
		PkgError ("Cannot copy 'TrueCrypt Setup.exe' to the package");
		return FALSE;
	}

	// Determine the buffer size needed for all the files and meta data and check if all required files exist

	bufLen = 0;

	for (i = 0; i < sizeof (szCompressedFiles) / sizeof (szCompressedFiles[0]); i++)
	{
		_snprintf (szTmpFilePath, sizeof(szTmpFilePath), "%s%s", szDestDir, szCompressedFiles[i]);

		if (!FileExists (szTmpFilePath))
		{
			char tmpstr [1000];

			_snprintf (tmpstr, sizeof(tmpstr), "File not found:\n\n'%s'", szTmpFilePath);
			remove (outputFile);
			PkgError (tmpstr);
			return FALSE;
		}

		bufLen += (int) GetFileSize64 (szTmpFilePath);

		bufLen += 2;					// 16-bit filename length
		bufLen += strlen(szCompressedFiles[i]);	// Filename
		bufLen += 4;					// CRC-32
		bufLen += 4;					// 32-bit file length
	}

	buffer = malloc (bufLen + 524288);	// + 512K reserve 
	if (buffer == NULL)
	{
		PkgError ("Cannot allocate memory for uncompressed data");
		remove (outputFile);
		return FALSE;
	}


	// Write the start marker
	if (!SaveBufferToFile (MAG_START_MARKER, outputFile, strlen (MAG_START_MARKER), TRUE))
	{
		PkgError ("Cannot write the start marker");
		remove (outputFile);
		return FALSE;
	}


	bufIndex = buffer;

	// Copy all required files and their meta data to the buffer
	for (i = 0; i < sizeof (szCompressedFiles) / sizeof (szCompressedFiles[0]); i++)
	{
		DWORD tmpFileSize;
		unsigned char *tmpBuffer;

		_snprintf (szTmpFilePath, sizeof(szTmpFilePath), "%s%s", szDestDir, szCompressedFiles[i]);

		tmpBuffer = LoadFile (szTmpFilePath, &tmpFileSize);

		if (tmpBuffer == NULL)
		{
			char tmpstr [1000];

			free (tmpBuffer);
			_snprintf (tmpstr, sizeof(tmpstr), "Cannot load file \n'%s'", szTmpFilePath);
			remove (outputFile);
			PkgError (tmpstr);
			goto msep_err;
		}

		// Copy the filename length to the main buffer
		mputWord (bufIndex, (WORD) strlen(szCompressedFiles[i]));

		// Copy the filename to the main buffer
		memcpy (bufIndex, szCompressedFiles[i], strlen(szCompressedFiles[i]));
		bufIndex += strlen(szCompressedFiles[i]);

		// Compute CRC-32 hash of the uncompressed file and copy it to the main buffer
		mputLong (bufIndex, GetCrc32 (tmpBuffer, tmpFileSize));

		// Copy the file length to the main buffer
		mputLong (bufIndex, (unsigned __int32) tmpFileSize);

		// Copy the file contents to the main buffer
		memcpy (bufIndex, tmpBuffer, tmpFileSize);
		bufIndex += tmpFileSize;

		free (tmpBuffer);
	}

	// Calculate the total size of the uncompressed data
	uncompressedDataLen = (int) (bufIndex - buffer);

	// Write total size of the uncompressed data
	szTmp32bitPtr = szTmp32bit;
	mputLong (szTmp32bitPtr, (unsigned __int32) uncompressedDataLen);
	if (!SaveBufferToFile (szTmp32bit, outputFile, sizeof (szTmp32bit), TRUE))
	{
		remove (outputFile);
		PkgError ("Cannot write the total size of the uncompressed data");
		return FALSE;
	}

	// Compress all the files and meta data in the buffer to create a solid archive

	compressedBuffer = malloc (uncompressedDataLen + 524288);	// + 512K reserve
	if (compressedBuffer == NULL)
	{
		remove (outputFile);
		PkgError ("Cannot allocate memory for compressed data");
		return FALSE;
	}

	compressedDataLen = CompressBuffer (compressedBuffer, buffer, uncompressedDataLen);
	if (compressedDataLen <= 0)
	{
		remove (outputFile);
		PkgError ("Failed to compress the data");
		return FALSE;
	}

	free (buffer);

	// Write the total size of the compressed data
	szTmp32bitPtr = szTmp32bit;
	mputLong (szTmp32bitPtr, (unsigned __int32) compressedDataLen);
	if (!SaveBufferToFile (szTmp32bit, outputFile, sizeof (szTmp32bit), TRUE))
	{
		remove (outputFile);
		PkgError ("Cannot write the total size of the compressed data");
		return FALSE;
	}

	// Write the compressed data
	if (!SaveBufferToFile (compressedBuffer, outputFile, compressedDataLen, TRUE))
	{
		remove (outputFile);
		PkgError ("Cannot write compressed data to the package");
		return FALSE;
	}

	// Write the end marker
	if (!SaveBufferToFile (MagEndMarker, outputFile, strlen (MagEndMarker), TRUE))
	{
		remove (outputFile);
		PkgError ("Cannot write the end marker");
		return FALSE;
	}

	free (compressedBuffer);

	// Compute and write CRC-32 hash of the entire package
	{
		DWORD tmpFileSize;
		char *tmpBuffer;

		tmpBuffer = LoadFile (outputFile, &tmpFileSize);

		if (tmpBuffer == NULL)
		{
			handleWin32Error (hwndDlg);
			remove (outputFile);
			PkgError ("Cannot load the package to compute CRC");
			return FALSE;
		}

		// Zero all bytes that change when the exe is digitally signed (except appended blocks).
		WipeSignatureAreas (tmpBuffer);

		szTmp32bitPtr = szTmp32bit;
		mputLong (szTmp32bitPtr, GetCrc32 (tmpBuffer, tmpFileSize));
		if (!SaveBufferToFile (szTmp32bit, outputFile, sizeof (szTmp32bit), TRUE))
		{
			remove (outputFile);
			PkgError ("Cannot write the total size of the compressed data");
			return FALSE;
		}

		free (tmpBuffer);
	}

	sprintf (tmpStr, "Self-extracting package successfully created (%s)", outputFile);
	PkgInfo (tmpStr);
	return TRUE;

msep_err:
	free (buffer);
	free (compressedBuffer);
	return FALSE;
}
Ejemplo n.º 8
0
BOOL CALLBACK HotkeysDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{	
	WORD lw = LOWORD (wParam);
	WORD hw = HIWORD (wParam);
	static BOOL bKeyScanOn;
	static BOOL bTPlaySoundOnSuccessfulHkDismount;
	static BOOL bTDisplayBalloonOnSuccessfulHkDismount;

	switch (msg)
	{
	case WM_INITDIALOG:
		{
			LVCOLUMNW col;
			HWND hList = GetDlgItem (hwndDlg, IDC_HOTKEY_LIST);

			bKeyScanOn = FALSE;
			nSelectedHotkeyId = -1;
			currentVKeyCode = 0;
			memcpy (tmpHotkeys, Hotkeys, sizeof(tmpHotkeys));
			memset (vkeysDown, 0, sizeof(vkeysDown));

			SendMessageW (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0,
				LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_LABELTIP 
				); 

			memset (&col,0,sizeof(col));               
			col.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT;  
			col.pszText = GetString ("ACTION");                           
			col.cx = CompensateXDPI (341);
			col.fmt = LVCFMT_LEFT;
			SendMessageW (hList,LVM_INSERTCOLUMNW,0,(LPARAM)&col);

			col.pszText = GetString ("SHORTCUT");  
			col.cx = CompensateXDPI (190);           
			col.fmt = LVCFMT_LEFT;
			SendMessageW (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&col);

			LocalizeDialog (hwndDlg, "IDD_HOTKEYS_DLG");

			SetCheckBox (hwndDlg, IDC_HK_MOD_CTRL, TRUE);
			SetCheckBox (hwndDlg, IDC_HK_MOD_SHIFT, FALSE);
			SetCheckBox (hwndDlg, IDC_HK_MOD_ALT, TRUE);
			SetCheckBox (hwndDlg, IDC_HK_MOD_WIN, FALSE);

			SetCheckBox (hwndDlg, IDC_HK_DISMOUNT_PLAY_SOUND, bPlaySoundOnSuccessfulHkDismount);
			SetCheckBox (hwndDlg, IDC_HK_DISMOUNT_BALLOON_TOOLTIP, bDisplayBalloonOnSuccessfulHkDismount);

			bTPlaySoundOnSuccessfulHkDismount = bPlaySoundOnSuccessfulHkDismount;
			bTDisplayBalloonOnSuccessfulHkDismount = bDisplayBalloonOnSuccessfulHkDismount;

			EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE);
			EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE);

			DisplayHotkeyList(hwndDlg);
			
			SetTimer (hwndDlg, 0xfe, 10, NULL);
			return 1;
		}

	case WM_TIMER:
		{
			if ((nSelectedHotkeyId > -1) && (GetFocus () == GetDlgItem (hwndDlg, IDC_HOTKEY_KEY)))
			{
				wchar_t keyName [MAX_KEY_COMB_NAME_LEN];
				UINT tmpVKeyCode;

				keyName[0] = 0;

				ScanAndProcessKey (&tmpVKeyCode, &keyName[0]);

				if (keyName[0] != 0)
				{
					currentVKeyCode = tmpVKeyCode;
					SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), keyName);
					EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), TRUE);
				}
				else if ((currentVKeyCode != 0) && GetKeyName (currentVKeyCode, keyName))
				{
					SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), keyName);
				}
			}
			return 1;
		}

	case WM_NOTIFY:
		if (wParam == IDC_HOTKEY_LIST)
		{
			if (((LPNMHDR) lParam)->code == LVN_ITEMACTIVATE
				|| ((LPNMHDR) lParam)->code == LVN_ITEMCHANGED && (((LPNMLISTVIEW) lParam)->uNewState & LVIS_FOCUSED))
			{
				LVITEM item;
				memset(&item,0,sizeof(item));
				nSelectedHotkeyId = ((LPNMLISTVIEW) lParam)->iItem;
				currentVKeyCode = 0;
				memset (vkeysDown, 0, sizeof(vkeysDown));
				SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), GetString ("PRESS_A_KEY_TO_ASSIGN"));

				EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), (tmpHotkeys[nSelectedHotkeyId].vKeyCode > 0));

				EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE);
				bKeyScanOn = TRUE;
				return 1;
			}
		}

		return 0;

	case WM_COMMAND:
		if (lw == IDC_HOTKEY_KEY && hw == EN_CHANGE)
		{
			if (!bKeyScanOn && nSelectedHotkeyId < 0 && GetWindowTextLengthW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY)))
				SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L"");
		}

		if (lw == IDC_HOTKEY_ASSIGN)
		{
			BOOL bOwnActiveShortcut = FALSE;

			if (nSelectedHotkeyId >= 0 && currentVKeyCode != 0)
			{
				UINT modifiers = 0; 
				if (GetCheckBox (hwndDlg, IDC_HK_MOD_CTRL))
					modifiers = MOD_CONTROL;

				if (GetCheckBox (hwndDlg, IDC_HK_MOD_ALT))
					modifiers |= MOD_ALT;

				if (GetCheckBox (hwndDlg, IDC_HK_MOD_SHIFT))
					modifiers |= MOD_SHIFT;

				if (GetCheckBox (hwndDlg, IDC_HK_MOD_WIN))
					modifiers |= MOD_WIN;

				// Check if it's not already assigned
				if (ShortcutInUse (currentVKeyCode, modifiers, tmpHotkeys))
				{
					Error ("SHORTCUT_ALREADY_IN_USE", hwndDlg);
					return 1;
				}

				// Check for reserved system keys
				switch (currentVKeyCode)
				{
				case VK_F1:
				case VK_F12:
					/* F1 is help and F12 is reserved for use by the debugger at all times */
					if (modifiers == 0)
					{
						Error ("CANNOT_USE_RESERVED_KEY", hwndDlg);
						return 1;
					}
					break;
				}

				bOwnActiveShortcut = ShortcutInUse (currentVKeyCode, modifiers, Hotkeys);

				// Test if the shortcut can be assigned without errors
				if (!bOwnActiveShortcut
					&& !RegisterHotKey (hwndDlg, nSelectedHotkeyId, modifiers, currentVKeyCode))
				{
					handleWin32Error(hwndDlg, SRC_POS);
					return 1;
				}
				else
				{
					if (!bOwnActiveShortcut && !UnregisterHotKey (hwndDlg, nSelectedHotkeyId))
						handleWin32Error(hwndDlg, SRC_POS);

					tmpHotkeys[nSelectedHotkeyId].vKeyCode = currentVKeyCode;
					tmpHotkeys[nSelectedHotkeyId].vKeyModifiers = modifiers;

					SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L"");
					EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE);
					EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE);
					nSelectedHotkeyId = -1;
					bKeyScanOn = FALSE;
					currentVKeyCode = 0;
					memset (vkeysDown, 0, sizeof(vkeysDown));
				}
			}
			DisplayHotkeyList(hwndDlg);
			return 1;
		}

		if (lw == IDC_HOTKEY_REMOVE)
		{
			if (nSelectedHotkeyId >= 0)
			{
				tmpHotkeys[nSelectedHotkeyId].vKeyCode = 0;
				tmpHotkeys[nSelectedHotkeyId].vKeyModifiers = 0;
				SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L"");
				EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE);
				EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE);
				nSelectedHotkeyId = -1;
				bKeyScanOn = FALSE;
				currentVKeyCode = 0;
				memset (vkeysDown, 0, sizeof(vkeysDown));
				DisplayHotkeyList(hwndDlg);
			}
			return 1;
		}

		if (lw == IDC_RESET_HOTKEYS)
		{
			int i;

			for (i = 0; i < NBR_HOTKEYS; i++)
			{
				tmpHotkeys[i].vKeyCode = 0;
				tmpHotkeys[i].vKeyModifiers = 0;
			}
			SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L"");
			EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE);
			EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE);
			nSelectedHotkeyId = -1;
			bKeyScanOn = FALSE;
			currentVKeyCode = 0;
			memset (vkeysDown, 0, sizeof(vkeysDown));
			DisplayHotkeyList(hwndDlg);
			return 1;
		}

		if (lw == IDC_HK_DISMOUNT_PLAY_SOUND)
		{
			bTPlaySoundOnSuccessfulHkDismount = GetCheckBox (hwndDlg, IDC_HK_DISMOUNT_PLAY_SOUND);
		}

		if (lw == IDC_HK_DISMOUNT_BALLOON_TOOLTIP)
		{
			bTDisplayBalloonOnSuccessfulHkDismount = GetCheckBox (hwndDlg, IDC_HK_DISMOUNT_BALLOON_TOOLTIP);
		}

		if (lw == IDCANCEL || lw == IDCLOSE)
		{
			KillTimer (hwndDlg, 0xfe);
			EndDialog (hwndDlg, IDCANCEL);
			return 1;
		}

		if (lw == IDOK)
		{
			HWND hwndMainDlg = hwndDlg;

			while (GetParent (hwndMainDlg) != NULL)
			{
				hwndMainDlg = GetParent (hwndMainDlg);
			}
			UnregisterAllHotkeys (hwndMainDlg, Hotkeys);
			memcpy (Hotkeys, tmpHotkeys, sizeof(Hotkeys));
			RegisterAllHotkeys (hwndMainDlg, Hotkeys);
			KillTimer (hwndDlg, 0xfe);
			bPlaySoundOnSuccessfulHkDismount = bTPlaySoundOnSuccessfulHkDismount;
			bDisplayBalloonOnSuccessfulHkDismount = bTDisplayBalloonOnSuccessfulHkDismount;

			SaveSettings (hwndDlg);
			EndDialog (hwndDlg, IDCANCEL);
			return 1;
		}
		return 0;

	case WM_CLOSE:

		KillTimer (hwndDlg, 0xfe);
		EndDialog (hwndDlg, IDCANCEL);
		return 1;
	}
	return 0;
}