LPADAPTER PacketOpenAdapter( LPCTSTR AdapterName, int16 mode ) { LPADAPTER lpAdapter; BOOLEAN Result = TRUE; D(bug("Packet32: PacketOpenAdapter\n")); // May fail if user is not an Administrator. StartPacketDriver( TEXT("B2ether") ); lpAdapter = (LPADAPTER)GlobalAllocPtr( GMEM_MOVEABLE|GMEM_ZEROINIT, sizeof(ADAPTER) ); if (lpAdapter==NULL) { D(bug("Packet32: PacketOpenAdapter GlobalAlloc Failed\n")); return NULL; } TCHAR device_name[256]; _sntprintf(lpAdapter->SymbolicLink, lengthof(lpAdapter->SymbolicLink), TEXT("\\\\.\\B2ether_%s"), AdapterName ); _sntprintf(device_name, lengthof(device_name), TEXT("\\Device\\B2ether_%s"), AdapterName ); // Work around one subtle NT4 bug. DefineDosDevice( DDD_REMOVE_DEFINITION, &lpAdapter->SymbolicLink[4], NULL ); DefineDosDevice( DDD_RAW_TARGET_PATH, &lpAdapter->SymbolicLink[4], device_name ); packet_filter = NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_MULTICAST | NDIS_PACKET_TYPE_BROADCAST; if(mode == ETHER_MULTICAST_ALL) packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; if(mode == ETHER_MULTICAST_PROMISCUOUS) packet_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; if (Result) { lpAdapter->hFile = CreateFile(lpAdapter->SymbolicLink, GENERIC_WRITE | GENERIC_READ, 0, NULL, // (os == VER_PLATFORM_WIN32_NT) ? CREATE_ALWAYS : OPEN_EXISTING, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 ); if (lpAdapter->hFile != INVALID_HANDLE_VALUE) { if(*AdapterName && _tcscmp(AdapterName,TEXT("<None>")) != 0) { PacketSetFilter( lpAdapter, packet_filter ); } return lpAdapter; } } D(bug("Packet32: PacketOpenAdapter Could not open adapter\n")); GlobalFreePtr( lpAdapter ); return NULL; }
BOOL CreateDriveLetter( WCHAR DriveLetter, LPCWSTR DeviceName) { WCHAR dosDevice[] = L"\\\\.\\C:"; WCHAR driveName[] = L"C:"; WCHAR rawDeviceName[MAX_PATH] = L"\\Device"; HANDLE device; dosDevice[4] = DriveLetter; driveName[0] = DriveLetter; wcscat(rawDeviceName, DeviceName); Logger::log(0,"DriveLetter: %wc, DeviceName %ws\n", DriveLetter, dosDevice); device = CreateFile( dosDevice, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL ); if (device != INVALID_HANDLE_VALUE) { Logger::logWinError(ERROR_DEVICE_IN_USE, "DokanControl Mount failed for %wc", DriveLetter); CloseHandle(device); return FALSE; } if (!DefineDosDevice(DDD_RAW_TARGET_PATH, driveName, rawDeviceName)) { Logger::logWinError(GetLastError(),"DokanControl DefineDosDevice failed"); return FALSE; } device = CreateFile( dosDevice, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL ); if (device == INVALID_HANDLE_VALUE) { Logger::logWinError(GetLastError(), "DokanControl Mount %wc failed", DriveLetter); DefineDosDevice(DDD_REMOVE_DEFINITION, dosDevice, NULL); return FALSE; } CloseHandle(device); return TRUE; }
BOOL CreateDriveLetter(WCHAR DriveLetter, LPCWSTR DeviceName) { WCHAR dosDevice[] = L"\\\\.\\C:"; WCHAR driveName[] = L"C:"; WCHAR rawDeviceName[MAX_PATH] = L"\\Device"; HANDLE device; dosDevice[4] = DriveLetter; driveName[0] = DriveLetter; wcscat_s(rawDeviceName, MAX_PATH, DeviceName); DokanDbgPrintW(L"DriveLetter: %c, DeviceName %s\n", DriveLetter, rawDeviceName); device = CreateFile( dosDevice, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL ); if (device != INVALID_HANDLE_VALUE) { DokanDbgPrintW(L"DokanControl Mount failed: %c: is alredy used\n", DriveLetter); CloseHandle(device); return FALSE; } if (!DefineDosDevice(DDD_RAW_TARGET_PATH, driveName, rawDeviceName)) { DokanDbgPrintW(L"DokanControl DefineDosDevice failed: %d\n", GetLastError()); return FALSE; } device = CreateFile( dosDevice, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL ); if (device == INVALID_HANDLE_VALUE) { DokanDbgPrintW(L"DokanControl Mount %c failed:%d\n", DriveLetter, GetLastError()); DefineDosDevice(DDD_REMOVE_DEFINITION, dosDevice, NULL); return FALSE; } CloseHandle(device); return TRUE; }
BOOL DokanControlUnmount( LPCWSTR MountPoint) { ULONG length = wcslen(MountPoint); if (length == 1 || (length == 2 && MountPoint[1] == L':') || (length == 3 && MountPoint[1] == L':' && MountPoint[2] == L'\\')) { WCHAR drive[] = L"C:"; drive[0] = MountPoint[0]; if (!DefineDosDevice(DDD_REMOVE_DEFINITION, drive, NULL)) { Logger::logWinError(GetLastError(), "DokanControl DefineDosDevice failed"); //Logger::log(0,"DriveLetter %wc\n", MountPoint[0]); return FALSE; } else { Logger::log(0,"DokanControl DD_REMOVE_DEFINITION success\n"); return TRUE; } } else if (length > 3 ) { return DeleteMountPoint(MountPoint); } return FALSE; }
DWORD MountDOSDrive(char chDrive,const char *szSubmount,BOOL bPersistent,const char * pUsername) { #ifdef AFSIFS DWORD err; BOOL succ; TCHAR szTokens[MAX_PATH], *tok; #endif /* AFSIFS */ TCHAR szPath[MAX_PATH]; TCHAR szClient[MAX_PATH]; TCHAR szDrive[3] = TEXT("?:"); #ifdef AFSIFS int pathCount, currPos, lastPos, x; pathCount = 0; pathCount = 0; strcpy(szTokens, szSubmount); tok = strtok(szTokens, "/\\"); strcpy(szPath, ""); while (tok) { if (pathCount || stricmp(tok, "afs")) { strcat(szPath, "\\"); strcat(szPath, tok); pathCount++; } tok = strtok(NULL, "/\\"); } sprintf(szDrive,"%c:",chDrive); strcpy(szTokens, szPath); sprintf(szPath,"\\Device\\afsrdr\\%d%s",pathCount,szTokens); //succ = DefineDosDevice(DDD_RAW_TARGET_PATH, "J:", "\\Device\\afsrdr\\2\\ericjw\\test"); succ = DefineDosDevice(DDD_RAW_TARGET_PATH, szDrive, szPath); err = GetLastError(); return succ ? NO_ERROR : ERROR_DEVICE_IN_USE; #else sprintf(szDrive,"%c:",chDrive); GetClientNetbiosName (szClient); sprintf(szPath,"\\\\%s\\%s",szClient,szSubmount); NETRESOURCE nr; memset (&nr, 0x00, sizeof(NETRESOURCE)); nr.dwType=RESOURCETYPE_DISK; nr.lpLocalName=szDrive; nr.lpRemoteName=szPath; nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */ DWORD res=WNetAddConnection2(&nr,NULL,pUsername,(bPersistent)?CONNECT_UPDATE_PROFILE:0); DEBUG_EVENT5("AFS DriveMap","Mount %s Local[%s] Remote[%s] User[%s]=%x", (bPersistent)?"Persistant" : "NonPresistant", szDrive,szPath,pUsername?pUsername:"******",res); return res; #endif }
int RemoveFakeDosName (char *lpszDiskFile, char *lpszDosDevice) { BOOL bDosLinkRemoved = DefineDosDevice (DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE | DDD_REMOVE_DEFINITION, lpszDosDevice, lpszDiskFile); if (bDosLinkRemoved == FALSE) { return ERR_OS_ERROR; } return 0; }
void OpenKeyboardDevice() { if(!DefineDosDevice(DDD_RAW_TARGET_PATH, "Kbd", "\\Device\\KeyboardClass0")) { failed(_T("OpenKeyboardDevice()")); } kbd = CreateFile("\\\\.\\Kbd", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (!kbd) { failed(_T("OpenKeyboardDevice()#2")); } }
bool DelSubstDrive(const wchar_t *DeviceName) { bool Result=false; string strTargetPath; if (GetSubstName(DRIVE_NOT_INIT,DeviceName,strTargetPath)) { strTargetPath=(string)L"\\??\\"+strTargetPath; Result=(DefineDosDevice(DDD_RAW_TARGET_PATH|DDD_REMOVE_DEFINITION|DDD_EXACT_MATCH_ON_REMOVE,DeviceName,strTargetPath)==TRUE); } return Result; }
DWORD DisMountDOSDrive(const char chDrive,BOOL bForce) { TCHAR szPath[MAX_PATH]; #ifdef AFSIFS DWORD succ; #endif sprintf(szPath,"%c:",chDrive); #ifdef AFSIFS succ = DefineDosDevice(DDD_REMOVE_DEFINITION, szPath, NULL); return (!succ) ? GetLastError() : 0; #else return DisMountDOSDriveFull(szPath,bForce); #endif }
int FakeDosNameForDevice (const char *lpszDiskFile, char *lpszDosDevice, char *lpszCFDevice, BOOL bNameOnly) { BOOL bDosLinkCreated = TRUE; sprintf (lpszDosDevice, "truecrypt%lu", GetCurrentProcessId ()); if (bNameOnly == FALSE) bDosLinkCreated = DefineDosDevice (DDD_RAW_TARGET_PATH, lpszDosDevice, lpszDiskFile); if (bDosLinkCreated == FALSE) return ERR_OS_ERROR; else sprintf (lpszCFDevice, "\\\\.\\%s", lpszDosDevice); return 0; }
int _tmain(int argc, _TCHAR* argv[]) { std::wstring symlink; std::wstring target; if (argc < 3) { printf("Usage: CreateDosDeviceSymlink [-d] symlink [target]\n"); printf("Options:\n"); printf("-d : Delete the symlink\n"); return 1; } if (wcscmp(argv[1], L"-d") == 0) { symlink = MakeSymlink(argv[2]); if (argc > 3) { target = argv[3]; } if (DefineDosDeviceW(DDD_NO_BROADCAST_SYSTEM | DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, symlink.c_str(), target.size() > 0 ? target.c_str() : nullptr)) { printf("Removed symlink\n"); } else { printf("Error removing symlink: %ls\n", GetErrorMessage().c_str()); } } else { symlink = MakeSymlink(argv[1]); target = argv[2]; if (DefineDosDevice(DDD_NO_BROADCAST_SYSTEM | DDD_RAW_TARGET_PATH, symlink.c_str(), target.c_str())) { printf("Created symlink\n"); } else { printf("Error creating symlink: %ls\n", GetErrorMessage().c_str()); } } return 0; }
void Cleanup(bool bAbnormalAbort, bool bSnapshotCreated, const CString& mountedDevice, CComPtr<IVssBackupComponents> pBackupComponents, GUID snapshotSetId) { if (pBackupComponents == NULL) { return; } if (bAbnormalAbort) { OutputWriter::WriteLine(TEXT("Aborting backup."), VERBOSITY_THRESHOLD_NORMAL); pBackupComponents->AbortBackup(); } if (!mountedDevice.IsEmpty()) { if (bAbnormalAbort) { CString message; message.AppendFormat(TEXT("Dismounting device: %s"), mountedDevice); OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL); } BOOL bWorked = DefineDosDevice(DDD_REMOVE_DEFINITION, mountedDevice, NULL); if (!bWorked) { DWORD error = ::GetLastError(); CString errorMessage; Utilities::FormatErrorMessage(error, errorMessage); CString message; message.AppendFormat(TEXT("There was an error calling DefineDosDevice during Cleanup. Error: %s"), errorMessage); OutputWriter::WriteLine(message); } } if (bSnapshotCreated) { if (bAbnormalAbort) { OutputWriter::WriteLine(TEXT("Deleting snapshot."), VERBOSITY_THRESHOLD_NORMAL); } LONG cDeletedSnapshots; GUID nonDeletedSnapshotId; pBackupComponents->DeleteSnapshots(snapshotSetId, VSS_OBJECT_SNAPSHOT_SET, TRUE, &cDeletedSnapshots, &nonDeletedSnapshotId); } }
BOOL DokanControlUnmount( WCHAR DriveLetter) { WCHAR volumeName[] = L"\\\\.\\ :"; HANDLE device; volumeName[4] = DriveLetter; /* device = CreateFile( volumeName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL ); if (device == INVALID_HANDLE_VALUE) { DbgPrintW(L"DriveLetter %wc\n", DriveLetter); DbgPrintW(L"DokanControl Unmount failed\n"); return FALSE; } CloseHandle(device); */ if (!DefineDosDevice(DDD_REMOVE_DEFINITION, &volumeName[4], NULL)) { DbgPrintW(L"DriveLetter %wc\n", DriveLetter); DbgPrintW(L"DokanControl DefineDosDevice failed\n"); return FALSE; } else { DbgPrintW(L"DokanControl DD_REMOVE_DEFINITION success\n"); } DeleteMountPoint(L"C:\\mount\\dokan"); return TRUE; }
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; }
int FileDiskUmount(char DriveLetter) { char VolumeName[] = "\\\\.\\ :"; char DriveName[] = " :\\"; HANDLE Device; DWORD BytesReturned; VolumeName[4] = DriveLetter; DriveName[0] = DriveLetter; Device = CreateFile( VolumeName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL ); if (Device == INVALID_HANDLE_VALUE) { PrintLastError(&VolumeName[4]); return -1; } if (!DeviceIoControl( Device, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &BytesReturned, NULL )) { PrintLastError(&VolumeName[4]); return -1; } if (!DeviceIoControl( Device, IOCTL_FILE_DISK_CLOSE_FILE, NULL, 0, NULL, 0, &BytesReturned, NULL )) { PrintLastError("FileDisk:"); return -1; } if (!DeviceIoControl( Device, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &BytesReturned, NULL )) { PrintLastError(&VolumeName[4]); return -1; } if (!DeviceIoControl( Device, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &BytesReturned, NULL )) { PrintLastError(&VolumeName[4]); return -1; } CloseHandle(Device); if (!DefineDosDevice( DDD_REMOVE_DEFINITION, &VolumeName[4], NULL )) { PrintLastError(&VolumeName[4]); return -1; } SHChangeNotify(SHCNE_DRIVEREMOVED, SHCNF_PATH, DriveName, NULL); return 0; }
int main(int argc, wchar_t* argv[]) { bool all = false; bool systemDriveSource = false; DWORD flags = 0; std::wstring sourcePath; std::wstring targetPath; argc--; argv++; //Remove program name while(argc) { //Accept if it's a switch -- that is, it begins with - or / if (wcslen(argv[0]) > 1 && (argv[0][0] == L'-' || argv[0][0] == L'/')) { //Loop through specified switches. for (wchar_t * strIt = argv[0] + 1; strIt != argv[0] + wcslen(argv[0]); strIt++) { switch (*strIt) { case L'A': case L'a': all = true; break; case L'S': case L's': systemDriveSource = true; break; case L'R': case L'r': flags |= DDD_RAW_TARGET_PATH; break; case L'D': case L'd': flags |= DDD_REMOVE_DEFINITION; break; case L'E': case L'e': flags |= DDD_EXACT_MATCH_ON_REMOVE; break; case L'N': case L'n': flags |= DDD_NO_BROADCAST_SYSTEM; default: throw std::runtime_error("Unrecognised option to DOSDEV!"); } } } else //NOT a switch { sourcePath = argv[0]; if (argc > 1) { targetPath = argv[1]; } break; //Commandline processing finished, break out of the FOR } argc--; argv++; } if (systemDriveSource) { wchar_t systemDrive[4]; targetPath = sourcePath; if (!ExpandEnvironmentStrings(L"%SYSTEMDRIVE%", systemDrive, 3)) throw std::runtime_error("Systemdrive could not be enumerated."); sourcePath.assign(systemDrive); } if (sourcePath.length()) //We are defining a device { DefineDosDevice(flags, sourcePath.c_str(), targetPath.empty() ? NULL : targetPath.c_str()); } //Print device list std::vector<std::wstring> driveStrings; wchar_t *drivesBuffer = NULL; DWORD error = 0; DWORD currentSize = 0; const DWORD incrementSize = 2048; do { delete [] drivesBuffer; currentSize += incrementSize; drivesBuffer = new wchar_t[currentSize]; error = QueryDosDevice(NULL, drivesBuffer, currentSize); } while (error == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return -1; for(wchar_t *bufferWalker = drivesBuffer; *bufferWalker; bufferWalker += wcslen(bufferWalker) + 1) { driveStrings.push_back(bufferWalker); } delete [] drivesBuffer; if (driveStrings.empty()) return 0; std::sort(driveStrings.begin(), driveStrings.end(), deviceSorter); std::vector<std::wstring>::const_iterator stringsWalker = driveStrings.begin(); for (; stringsWalker != driveStrings.end() && StringIsDriveLetter(*stringsWalker); stringsWalker++) { displayDevice(*stringsWalker); } if (all && stringsWalker != driveStrings.end()) { logger << L"\r\n"; for (; stringsWalker != driveStrings.end(); stringsWalker++) { displayDevice(*stringsWalker); } } #ifndef NDEBUG system("pause"); #endif return 0; }
void CloseKeyboardDevice() { DefineDosDevice(DDD_REMOVE_DEFINITION, "Kbd", NULL); CloseHandle(kbd); }
bool DelSubstDrive(const string& DeviceName) { string strTargetPath; return os::fs::QueryDosDevice(DeviceName, strTargetPath) && DefineDosDevice(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, DeviceName.c_str(), strTargetPath.c_str()) != FALSE; }
int FileDiskMount( int DeviceNumber, POPEN_FILE_INFORMATION OpenFileInformation, BOOLEAN CdImage ) { char VolumeName[] = "\\\\.\\ :"; char DriveName[] = " :\\"; char DeviceName[255]; HANDLE Device; DWORD BytesReturned; VolumeName[4] = OpenFileInformation->DriveLetter; DriveName[0] = OpenFileInformation->DriveLetter; Device = CreateFile( VolumeName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL ); if (Device != INVALID_HANDLE_VALUE) { SetLastError(ERROR_BUSY); PrintLastError(&VolumeName[4]); return -1; } if (CdImage) { sprintf(DeviceName, DEVICE_NAME_PREFIX "Cd" "%u", DeviceNumber); } else { sprintf(DeviceName, DEVICE_NAME_PREFIX "%u", DeviceNumber); } if (!DefineDosDevice( DDD_RAW_TARGET_PATH, &VolumeName[4], DeviceName )) { PrintLastError(&VolumeName[4]); return -1; } Device = CreateFile( VolumeName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL ); if (Device == INVALID_HANDLE_VALUE) { PrintLastError(&VolumeName[4]); DefineDosDevice(DDD_REMOVE_DEFINITION, &VolumeName[4], NULL); return -1; } if (!DeviceIoControl( Device, IOCTL_FILE_DISK_OPEN_FILE, OpenFileInformation, sizeof(OPEN_FILE_INFORMATION) + OpenFileInformation->FileNameLength - 1, NULL, 0, &BytesReturned, NULL )) { PrintLastError("FileDisk:"); DefineDosDevice(DDD_REMOVE_DEFINITION, &VolumeName[4], NULL); return -1; } SHChangeNotify(SHCNE_DRIVEADD, SHCNF_PATH, DriveName, NULL); return 0; }
int _tmain(int argc, _TCHAR* argv[]) { //::DebugBreak(); OutputWriter::SetVerbosityLevel(VERBOSITY_LEVEL_NORMAL); OutputWriter::WriteLine(TEXT("ShadowSpawn (c) 2011 Craig Andera. [email protected]"), VERBOSITY_THRESHOLD_UNLESS_SILENT); OutputWriter::WriteLine(TEXT(""), VERBOSITY_THRESHOLD_UNLESS_SILENT); bool bAbnormalAbort = true; DWORD exitCode = 0; int fileCount = 0; LONGLONG byteCount = 0; int directoryCount = 0; int skipCount = 0; SYSTEMTIME startTime; try { COptions options = COptions::Parse(argc, argv); if (options.get_Debug()) { ::DebugBreak(); } OutputWriter::SetVerbosityLevel((VERBOSITY_LEVEL) options.get_VerbosityLevel()); for (int i = 0; i < argc; ++i) { CString message; message.AppendFormat(TEXT("Argument %d: %s"), i, argv[i]); OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_IF_VERBOSE); } if (!Utilities::DirectoryExists(options.get_Source())) { CString message; message.AppendFormat(TEXT("Source path is not an existing directory: %s"), options.get_Source()); throw new CShadowSpawnException(message); } OutputWriter::WriteLine(TEXT("Calling CoInitialize")); CHECK_HRESULT(::CoInitialize(NULL)); CHECK_HRESULT( ::CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE, NULL)); ::GetSystemTime(&startTime); CString startTimeString; Utilities::FormatDateTime(&startTime, TEXT(" "), false, startTimeString); CString message; message.AppendFormat(TEXT("Shadowing %s at %s"), options.get_Source(), options.get_Device()); OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL); GUID systemProviderId = GetSystemProviderID(); OutputWriter::WriteLine(TEXT("Calling CreateVssBackupComponents")); CHECK_HRESULT(::CreateVssBackupComponents(&pBackupComponents)); OutputWriter::WriteLine(TEXT("Calling InitializeForBackup")); CHECK_HRESULT(pBackupComponents->InitializeForBackup()); CComPtr<IVssAsync> pWriterMetadataStatus; OutputWriter::WriteLine(TEXT("Calling GatherWriterMetadata")); CHECK_HRESULT(pBackupComponents->GatherWriterMetadata(&pWriterMetadataStatus)); OutputWriter::WriteLine(TEXT("Waiting for call to GatherWriterMetadata to finish...")); CHECK_HRESULT(pWriterMetadataStatus->Wait()); HRESULT hrGatherStatus; OutputWriter::WriteLine(TEXT("Calling QueryStatus for GatherWriterMetadata")); CHECK_HRESULT(pWriterMetadataStatus->QueryStatus(&hrGatherStatus, NULL)); if (hrGatherStatus == VSS_S_ASYNC_CANCELLED) { throw new CShadowSpawnException(L"GatherWriterMetadata was cancelled."); } OutputWriter::WriteLine(TEXT("Call to GatherWriterMetadata finished.")); OutputWriter::WriteLine(TEXT("Calling GetWriterMetadataCount")); vector<CWriter> writers; UINT cWriters; CHECK_HRESULT(pBackupComponents->GetWriterMetadataCount(&cWriters)); for (UINT iWriter = 0; iWriter < cWriters; ++iWriter) { CWriter writer; CComPtr<IVssExamineWriterMetadata> pExamineWriterMetadata; GUID id; OutputWriter::WriteLine(TEXT("Calling GetWriterMetadata")); CHECK_HRESULT(pBackupComponents->GetWriterMetadata(iWriter, &id, &pExamineWriterMetadata)); GUID idInstance; GUID idWriter; BSTR bstrWriterName; VSS_USAGE_TYPE usage; VSS_SOURCE_TYPE source; CHECK_HRESULT(pExamineWriterMetadata->GetIdentity(&idInstance, &idWriter, &bstrWriterName, &usage, &source)); writer.set_InstanceId(idInstance); writer.set_Name(bstrWriterName); writer.set_WriterId(idWriter); CComBSTR writerName(bstrWriterName); CString message; message.AppendFormat(TEXT("Writer %d named %s"), iWriter, (LPCTSTR) writerName); OutputWriter::WriteLine(message); UINT cIncludeFiles; UINT cExcludeFiles; UINT cComponents; CHECK_HRESULT(pExamineWriterMetadata->GetFileCounts(&cIncludeFiles, &cExcludeFiles, &cComponents)); message.Empty(); message.AppendFormat(TEXT("Writer has %d components"), cComponents); OutputWriter::WriteLine(message); for (UINT iComponent = 0; iComponent < cComponents; ++iComponent) { CWriterComponent component; CComPtr<IVssWMComponent> pComponent; CHECK_HRESULT(pExamineWriterMetadata->GetComponent(iComponent, &pComponent)); PVSSCOMPONENTINFO pComponentInfo; CHECK_HRESULT(pComponent->GetComponentInfo(&pComponentInfo)); CString message; message.AppendFormat(TEXT("Component %d is named %s, has a path of %s, and is %sselectable for backup. %d files, %d databases, %d log files."), iComponent, pComponentInfo->bstrComponentName, pComponentInfo->bstrLogicalPath, pComponentInfo->bSelectable ? TEXT("") : TEXT("not "), pComponentInfo->cFileCount, pComponentInfo->cDatabases, pComponentInfo->cLogFiles); OutputWriter::WriteLine(message); component.set_LogicalPath(pComponentInfo->bstrLogicalPath); component.set_SelectableForBackup(pComponentInfo->bSelectable); component.set_Writer(iWriter); component.set_Name(pComponentInfo->bstrComponentName); component.set_Type(pComponentInfo->type); for (UINT iFile = 0; iFile < pComponentInfo->cFileCount; ++iFile) { CComPtr<IVssWMFiledesc> pFileDesc; CHECK_HRESULT(pComponent->GetFile(iFile, &pFileDesc)); CComBSTR bstrPath; CHECK_HRESULT(pFileDesc->GetPath(&bstrPath)); CComBSTR bstrFileSpec; CHECK_HRESULT(pFileDesc->GetFilespec(&bstrFileSpec)); CString message; message.AppendFormat(TEXT("File %d has path %s\\%s"), iFile, bstrPath, bstrFileSpec); OutputWriter::WriteLine(message); } for (UINT iDatabase = 0; iDatabase < pComponentInfo->cDatabases; ++iDatabase) { CComPtr<IVssWMFiledesc> pFileDesc; CHECK_HRESULT(pComponent->GetDatabaseFile(iDatabase, &pFileDesc)); CComBSTR bstrPath; CHECK_HRESULT(pFileDesc->GetPath(&bstrPath)); CComBSTR bstrFileSpec; CHECK_HRESULT(pFileDesc->GetFilespec(&bstrFileSpec)); CString message; message.AppendFormat(TEXT("Database file %d has path %s\\%s"), iDatabase, bstrPath, bstrFileSpec); OutputWriter::WriteLine(message); } for (UINT iDatabaseLogFile = 0; iDatabaseLogFile < pComponentInfo->cLogFiles; ++iDatabaseLogFile) { CComPtr<IVssWMFiledesc> pFileDesc; CHECK_HRESULT(pComponent->GetDatabaseLogFile(iDatabaseLogFile, &pFileDesc)); CComBSTR bstrPath; CHECK_HRESULT(pFileDesc->GetPath(&bstrPath)); CComBSTR bstrFileSpec; CHECK_HRESULT(pFileDesc->GetFilespec(&bstrFileSpec)); CString message; message.AppendFormat(TEXT("Database log file %d has path %s\\%s"), iDatabaseLogFile, bstrPath, bstrFileSpec); OutputWriter::WriteLine(message); } CHECK_HRESULT(pComponent->FreeComponentInfo(pComponentInfo)); writer.get_Components().push_back(component); } writer.ComputeComponentTree(); for (unsigned int iComponent = 0; iComponent < writer.get_Components().size(); ++iComponent) { CWriterComponent& component = writer.get_Components()[iComponent]; CString message; message.AppendFormat(TEXT("Component %d has name %s, path %s, is %sselectable for backup, and has parent %s"), iComponent, component.get_Name(), component.get_LogicalPath(), component.get_SelectableForBackup() ? TEXT("") : TEXT("not "), component.get_Parent() == NULL ? TEXT("(no parent)") : component.get_Parent()->get_Name()); OutputWriter::WriteLine(message); } writers.push_back(writer); } OutputWriter::WriteLine(TEXT("Calling StartSnapshotSet")); CHECK_HRESULT(pBackupComponents->StartSnapshotSet(&snapshotSetId)); OutputWriter::WriteLine(TEXT("Calling GetVolumePathName")); WCHAR wszVolumePathName[MAX_PATH]; BOOL bWorked = ::GetVolumePathName(options.get_Source(), wszVolumePathName, MAX_PATH); if (!bWorked) { DWORD error = ::GetLastError(); CString errorMessage; Utilities::FormatErrorMessage(error, errorMessage); CString message; message.AppendFormat(TEXT("There was an error retrieving the volume name from the path. Path: %s Error: %s"), options.get_Source(), errorMessage); throw new CShadowSpawnException(message.GetString()); } OutputWriter::WriteLine(TEXT("Calling AddToSnapshotSet")); GUID snapshotId; CHECK_HRESULT(pBackupComponents->AddToSnapshotSet(wszVolumePathName, systemProviderId, &snapshotId)); for (unsigned int iWriter = 0; iWriter < writers.size(); ++iWriter) { CWriter writer = writers[iWriter]; CString message; message.AppendFormat(TEXT("Adding components to snapshot set for writer %s"), writer.get_Name()); OutputWriter::WriteLine(message); for (unsigned int iComponent = 0; iComponent < writer.get_Components().size(); ++iComponent) { CWriterComponent component = writer.get_Components()[iComponent]; if (ShouldAddComponent(component)) { CString message; message.AppendFormat(TEXT("Adding component %s (%s) from writer %s"), component.get_Name(), component.get_LogicalPath(), writer.get_Name()); OutputWriter::WriteLine(message); CHECK_HRESULT(pBackupComponents->AddComponent( writer.get_InstanceId(), writer.get_WriterId(), component.get_Type(), component.get_LogicalPath(), component.get_Name() )); } else { CString message; message.AppendFormat(TEXT("Not adding component %s from writer %s."), component.get_Name(), writer.get_Name()); OutputWriter::WriteLine(message); } } } OutputWriter::WriteLine(TEXT("Calling SetBackupState")); CHECK_HRESULT(pBackupComponents->SetBackupState(TRUE, FALSE, options.get_BackupType(), FALSE)); OutputWriter::WriteLine(TEXT("Calling PrepareForBackup")); CComPtr<IVssAsync> pPrepareForBackupResults; CHECK_HRESULT(pBackupComponents->PrepareForBackup(&pPrepareForBackupResults)); OutputWriter::WriteLine(TEXT("Waiting for call to PrepareForBackup to finish...")); CHECK_HRESULT(pPrepareForBackupResults->Wait()); HRESULT hrPrepareForBackupResults; CHECK_HRESULT(pPrepareForBackupResults->QueryStatus(&hrPrepareForBackupResults, NULL)); if (hrPrepareForBackupResults != VSS_S_ASYNC_FINISHED) { throw new CShadowSpawnException(TEXT("Prepare for backup failed.")); } OutputWriter::WriteLine(TEXT("Call to PrepareForBackup finished.")); SYSTEMTIME snapshotTime; ::GetSystemTime(&snapshotTime); bWorked = ::SetConsoleCtrlHandler(CtrlHandler, TRUE); if (!bWorked) { OutputWriter::WriteLine(TEXT("Unable to set control handler. Ctrl-C and Ctrl-Break may have undesirable results."), VERBOSITY_THRESHOLD_NORMAL); } if (!options.get_Simulate()) { OutputWriter::WriteLine(TEXT("Calling DoSnapshotSet")); CComPtr<IVssAsync> pDoSnapshotSetResults; CHECK_HRESULT(pBackupComponents->DoSnapshotSet(&pDoSnapshotSetResults)); OutputWriter::WriteLine(TEXT("Waiting for call to DoSnapshotSet to finish...")); CHECK_HRESULT(pDoSnapshotSetResults->Wait()); bSnapshotCreated = true; HRESULT hrDoSnapshotSetResults; CHECK_HRESULT(pDoSnapshotSetResults->QueryStatus(&hrDoSnapshotSetResults, NULL)); if (hrDoSnapshotSetResults != VSS_S_ASYNC_FINISHED) { throw new CShadowSpawnException(L"DoSnapshotSet failed."); } OutputWriter::WriteLine(TEXT("Call to DoSnapshotSet finished.")); OutputWriter::WriteLine(TEXT("Calling GetSnapshotProperties")); VSS_SNAPSHOT_PROP snapshotProperties; CHECK_HRESULT(pBackupComponents->GetSnapshotProperties(snapshotId, &snapshotProperties)); OutputWriter::WriteLine(TEXT("Calling CalculateSourcePath")); // TODO: We'll eventually have to deal with mount points CString wszSource; CalculateSourcePath( snapshotProperties.m_pwszSnapshotDeviceObject, options.get_Source(), wszVolumePathName, wszSource ); OutputWriter::WriteLine(TEXT("Calling DefineDosDevice to mount device.")); if (0 == wszSource.Find(TEXT("\\\\?\\GLOBALROOT"))) { wszSource = wszSource.Mid(_tcslen(TEXT("\\\\?\\GLOBALROOT"))); } bWorked = DefineDosDevice(DDD_RAW_TARGET_PATH, options.get_Device(), wszSource); if (!bWorked) { DWORD error = ::GetLastError(); CString errorMessage; Utilities::FormatErrorMessage(error, errorMessage); CString message; message.AppendFormat(TEXT("There was an error calling DefineDosDevice when mounting a device. Error: %s"), errorMessage); throw new CShadowSpawnException(message.GetString()); } mountedDevice = options.get_Device(); STARTUPINFO startUpInfo; memset(&startUpInfo, 0, sizeof(startUpInfo)); startUpInfo.cb = sizeof(startUpInfo); PROCESS_INFORMATION processInformation; size_t commandLength = options.get_Command().size(); wchar_t* copyCommand = (wchar_t*)_alloca((commandLength+1)*sizeof(wchar_t)); options.get_Command().copy(copyCommand, commandLength); copyCommand[commandLength] = L'\0'; message.Format(TEXT("Launching command: %s"), options.get_Command().c_str()); OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL); bWorked = CreateProcess(NULL, copyCommand, NULL, NULL, FALSE, 0, NULL, NULL, &startUpInfo, &processInformation); if (!bWorked) { DWORD error = ::GetLastError(); CString errorMessage; Utilities::FormatErrorMessage(error, errorMessage); CString message; message.AppendFormat(TEXT("There was an error calling CreateProcess. Process: %s Error: %s"), options.get_Command().c_str(), errorMessage); throw new CShadowSpawnException(message.GetString()); } WaitForSingleObject(processInformation.hProcess, INFINITE); bWorked = GetExitCodeProcess(processInformation.hProcess, &exitCode); if (!bWorked) { DWORD error = ::GetLastError(); CString errorMessage; Utilities::FormatErrorMessage(error, errorMessage); CString message; message.AppendFormat(TEXT("There was an error calling GetExitCodeProcess. Error: %s"), errorMessage); throw new CShadowSpawnException(message.GetString()); } CloseHandle(processInformation.hThread); CloseHandle(processInformation.hProcess); message.Format(TEXT("Launched command finished with exit code: %d."), exitCode); OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL); OutputWriter::WriteLine(TEXT("Calling DefineDosDevice to remove device.")); bWorked = DefineDosDevice(DDD_REMOVE_DEFINITION, options.get_Device(), NULL); if (!bWorked) { DWORD error = ::GetLastError(); CString errorMessage; Utilities::FormatErrorMessage(error, errorMessage); CString message; message.AppendFormat(TEXT("There was an error calling DefineDosDevice. Error: %s"), errorMessage); throw new CShadowSpawnException(message.GetString()); } mountedDevice.Empty(); OutputWriter::WriteLine(TEXT("Calling BackupComplete")); CComPtr<IVssAsync> pBackupCompleteResults; CHECK_HRESULT(pBackupComponents->BackupComplete(&pBackupCompleteResults)); OutputWriter::WriteLine(TEXT("Waiting for call to BackupComplete to finish...")); CHECK_HRESULT(pBackupCompleteResults->Wait()); HRESULT hrBackupCompleteResults; CHECK_HRESULT(pBackupCompleteResults->QueryStatus(&hrBackupCompleteResults, NULL)); if (hrBackupCompleteResults != VSS_S_ASYNC_FINISHED) { throw new CShadowSpawnException(TEXT("Completion of backup failed.")); } OutputWriter::WriteLine(TEXT("Call to BackupComplete finished.")); bAbnormalAbort = false; } } catch (CComException* e) { Cleanup(bAbnormalAbort, bSnapshotCreated, mountedDevice, pBackupComponents, snapshotSetId); CString message; CString file; e->get_File(file); message.Format(TEXT("There was a COM failure 0x%x - %s (%d)"), e->get_Hresult(), file, e->get_Line()); OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_UNLESS_SILENT); return 1; } catch (CShadowSpawnException* e) { Cleanup(bAbnormalAbort, bSnapshotCreated, mountedDevice, pBackupComponents, snapshotSetId); OutputWriter::WriteLine(e->get_Message(), VERBOSITY_THRESHOLD_UNLESS_SILENT); return 1; } catch (CParseOptionsException* e) { Cleanup(bAbnormalAbort, bSnapshotCreated, mountedDevice, pBackupComponents, snapshotSetId); CString message; message.AppendFormat(TEXT("Error: %s\n"), e->get_Message()); OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_UNLESS_SILENT); OutputWriter::WriteLine(COptions::get_Usage(), VERBOSITY_THRESHOLD_UNLESS_SILENT); return 2; } Cleanup(false, bSnapshotCreated, mountedDevice, pBackupComponents, snapshotSetId); OutputWriter::WriteLine(TEXT("Shadowing successfully completed."), VERBOSITY_THRESHOLD_NORMAL); if (exitCode != 0) { return (0x8000 | exitCode); } return 0; }
BOOL DokanControlMount( ULONG DeviceNumber, WCHAR DriveLetter) { WCHAR volumeName[] = L"\\\\.\\ :"; WCHAR driveLetterAndSlash[] = L"C:\\"; HANDLE device; WCHAR deviceName[MAX_PATH]; WCHAR mountPoint[MAX_PATH]; wsprintf(deviceName, DOKAN_RAW_DEVICE_NAME, DeviceNumber); wsprintf(mountPoint, DOKAN_MOUNT_DEVICE_NAME, DeviceNumber); volumeName[4] = DriveLetter; driveLetterAndSlash[0] = DriveLetter; DbgPrintW(L"DeviceNumber %d DriveLetter %c\n", DeviceNumber, DriveLetter); DbgPrintW(L"DeviceName %s\n",deviceName); device = CreateFile( volumeName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL ); if (device != INVALID_HANDLE_VALUE) { DbgPrintW(L"DokanControl Mount failed: %wc: is alredy used\n", DriveLetter); CloseHandle(device); return FALSE; } if (!DefineDosDevice(DDD_RAW_TARGET_PATH, &volumeName[4], deviceName)) { DbgPrintW(L"DokanControl DefineDosDevice failed: %d\n", GetLastError()); return FALSE; } /* NOTE: IOCTL_MOUNTDEV_QUERY_DEVICE_NAME in sys/device.cc handles GetVolumeNameForVolumeMountPoint. But it returns error even if driver return success. */ //wsprintf(deviceName, L"\\\\?\\Volume{dca0e0a5-d2ca-4f0f-8416-a6414657a77a}\\"); //DbgPrintW(L"DeviceName %s\n",deviceName); /* if (!GetVolumeNameForVolumeMountPoint( driveLetterAndSlash, deviceName, MAX_PATH)) { DbgPrint("Error: GetVolumeNameForVolumeMountPoint failed : %d\n", GetLastError()); } else { DbgPrintW(L"UniqueVolumeName %s\n", deviceName); DefineDosDevice(DDD_REMOVE_DEFINITION, &volumeName[4], NULL); if (!SetVolumeMountPoint(driveLetterAndSlash, deviceName)) { DbgPrint("Error: SetVolumeMountPoint failed : %d\n", GetLastError()); return FALSE; } } */ //CreateMountPoint(L"C:\\mount\\dokan", L"\\??\\E:\\test4"); //CreateMountPoint(L"C:\\mount\\dokan", L"\\??\\Volume{dca0e0a5-d2ca-4f0f-8416-a6414657a77a}\\"); //CreateMountPoint(L"C:\\mount\\dokan", mountPoint); device = CreateFile( volumeName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL ); if (device == INVALID_HANDLE_VALUE) { DbgPrintW(L"DokanControl Mount %ws failed:%d\n", volumeName, GetLastError()); DefineDosDevice(DDD_REMOVE_DEFINITION, &volumeName[4], NULL); return FALSE; } CloseHandle(device); return TRUE; }