/* * Copyright (c) 2010 Michael J. Wood * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef _XBOX #include #include #define INVALID_FILE_ATTRIBUTES -1 DWORD AG_XBOX_GetXbeTitleId(const char *xbePath) { HANDLE h; DWORD titleId = -1; DWORD loadAddress; DWORD certLocation; DWORD bytesRead; ANSI_STRING file; OBJECT_ATTRIBUTES attr; IO_STATUS_BLOCK status; if(!xbePath) return -1; RtlInitAnsiString(&file, xbePath); InitializeObjectAttributes(&attr, &file, OBJ_CASE_INSENSITIVE, NULL); if(SUCCEEDED(NtCreateFile(&h, FILE_GENERIC_READ, &attr, &status, NULL, 0, 0, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT))) { if(SetFilePointer(h, 0x104, NULL, FILE_BEGIN) == 0x104) { ReadFile(h, &loadAddress, sizeof(DWORD), &bytesRead, NULL); if(bytesRead == sizeof(DWORD)) { if(SetFilePointer(h, 0x118, NULL, FILE_BEGIN ) == 0x118) { ReadFile(h, &certLocation, sizeof(DWORD), &bytesRead, NULL); if(bytesRead == sizeof(DWORD)) { certLocation -= loadAddress; certLocation += 8; titleId = 0; if(SetFilePointer(h, certLocation, NULL, FILE_BEGIN) == certLocation) { ReadFile(h, &titleId, sizeof(DWORD), &bytesRead, NULL); if(bytesRead != sizeof(DWORD)) { titleId = 0; } } } } } } CloseHandle(h); } return titleId; } char* AG_XBOX_GetDeviceFromLogicalDrive(const char *drive) { HANDLE h; ANSI_STRING szDevice; ANSI_STRING szDrive; OBJECT_ATTRIBUTES attr; ULONG size; char devBuf[256]; char driveL[3]; char driveP[7]; if(!drive || strlen(drive) < 2 || !isalpha(drive[0]) || drive[1] != ':') { return NULL; } Strlcpy(driveL, drive, sizeof(driveL)); Snprintf(driveP, sizeof(driveP), "\\??\\%s", driveL); RtlInitAnsiString(&szDrive, driveP); szDevice.Buffer = devBuf; szDevice.Length = 0xf; szDevice.MaximumLength = 256; InitializeObjectAttributes(&attr, &szDrive, OBJ_CASE_INSENSITIVE, NULL); if(SUCCEEDED(NtOpenSymbolicLinkObject(&h, &attr))) { if(SUCCEEDED(NtQuerySymbolicLinkObject(h, &szDevice, &size))) { Strlcpy(devBuf, szDevice.Buffer, size + 1); CloseHandle(h); return TryStrdup(devBuf); } CloseHandle(h); } return NULL; } BOOL AG_XBOX_DriveIsMounted(const char driveLetter) { char path[3]; char *dev; if(!isalpha(driveLetter)) { return FALSE; } path[0] = driveLetter; path[1] = ':'; path[2] = '\0'; if((dev = AG_XBOX_GetDeviceFromLogicalDrive(path)) == NULL) { return FALSE; } Free(dev); return TRUE; } BOOL AG_XBOX_PathIsValid(const char *path) { DWORD attr; if(path && (attr = GetFileAttributes(path)) != INVALID_FILE_ATTRIBUTES) { if(attr & FILE_ATTRIBUTE_DIRECTORY) { return TRUE; } } return FALSE; } DWORD AG_XBOX_GetLogicalDrives() { DWORD d; int i; for (i = 0; i < 26; i++) { if(AG_XBOX_DriveIsMounted('A'+i)) { d |= (1 << i); } else { d &= ~(1 << i); } } return d; } #endif /* _XBOX */