A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 282 lines 10 kB view raw
1/* 2 * Windows MTP Firmware Uploading Implementation 3 * 4 * Based on http://opensource.creative.com/mtp_xfer.html 5 * Edited by Maurus Cuelenaere for Rockbox 6 * 7 * Copyright (c) 2009, Maurus Cuelenaere 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions are met: 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * * Neither the name of the <organization> nor the 18 * names of its contributors may be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY MAURUS CUELENAERE ''AS IS'' AND ANY 22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL MAURUS CUELENAERE BE LIABLE FOR ANY 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 34#include <windows.h> 35#include "mswmdm_i.c" 36#include "mswmdm.h" 37#include "sac.h" 38#include "scclient.h" 39 40#include "progresshelper.h" 41#include "MTP_DLL.h" 42 43/* 44 * Compilation requirements: 45 * 46 * Download the Windows Media Format 9.5 SDK 47 * Add "c:\wmsdk\wmfsdk95\include,c:\wmsdk\wmfsdk95\wmdm\inc" to your inclusion path 48 * Add "c:\wmsdk\wmfsdk95\lib,c:\wmsdk\wmfsdk95\wmdm\lib" to your library inclusion path 49 * Link to "mssachlp.lib" 50 * 51 */ 52 53struct mtp_if { 54 IComponentAuthenticate* pICompAuth; 55 CSecureChannelClient *pSacClient; 56 IWMDeviceManager3* pIdvMgr; 57 bool initialized; 58}; 59 60 61extern "C" { 62static int mtp_init(struct mtp_if* mtp) 63{ 64 HRESULT hr; 65 mtp->pSacClient = new CSecureChannelClient; 66 mtp->pIdvMgr = NULL; 67 mtp->initialized = false; 68 69 /* these are generic keys */ 70 BYTE abPVK[] = {0x00}; 71 BYTE abCert[] = {0x00}; 72 73 CoInitialize(NULL); 74 75 /* get an authentication interface */ 76 hr = CoCreateInstance(CLSID_MediaDevMgr, NULL, CLSCTX_ALL, 77 IID_IComponentAuthenticate, (void **)&mtp->pICompAuth); 78 if SUCCEEDED(hr) 79 { 80 /* create a secure channel client certificate */ 81 hr = mtp->pSacClient->SetCertificate(SAC_CERT_V1, (BYTE*) abCert, 82 sizeof(abCert), (BYTE*) abPVK, sizeof(abPVK)); 83 if SUCCEEDED(hr) 84 { 85 /* bind the authentication interface to the secure channel client */ 86 mtp->pSacClient->SetInterface(mtp->pICompAuth); 87 88 /* trigger communication */ 89 hr = mtp->pSacClient->Authenticate(SAC_PROTOCOL_V1); 90 if SUCCEEDED(hr) 91 { 92 /* get main interface to media device manager */ 93 hr = mtp->pICompAuth->QueryInterface(IID_IWMDeviceManager2, 94 (void**)&mtp->pIdvMgr); 95 if SUCCEEDED(hr) 96 { 97 mtp->initialized = true; 98 } 99 } 100 } 101 } 102 else { 103 CoUninitialize(); 104 } 105 return mtp->initialized; 106} 107 108 109static int mtp_close(struct mtp_if* mtp) 110{ 111 if(mtp->initialized) 112 { 113 mtp->pIdvMgr->Release(); 114 mtp->pICompAuth->Release(); 115 CoUninitialize(); 116 mtp->initialized = false; 117 } 118 return 0; 119} 120 121MTP_DLL_API int mtp_description(wchar_t* name, wchar_t* manufacturer, DWORD* version) 122{ 123 HRESULT hr; 124 int num = 0; 125 struct mtp_if mtp; 126 /* zero mtp structure */ 127 memset(&mtp, 0, sizeof(struct mtp_if)); 128 129 /* initialize interface */ 130 mtp_init(&mtp); 131 if(mtp.initialized == false) { 132 return -1; 133 } 134 135 /* we now have a media device manager interface... */ 136 /* enumerate devices... */ 137 IWMDMEnumDevice *pIEnumDev; 138 wchar_t pwsString[256]; 139 hr = mtp.pIdvMgr->EnumDevices2(&pIEnumDev); 140 if SUCCEEDED(hr) { 141 hr = pIEnumDev->Reset(); /* Next will now return the first device */ 142 if SUCCEEDED(hr) { 143 IWMDMDevice3* pIDevice; 144 unsigned long ulNumFetched; 145 hr = pIEnumDev->Next(1, (IWMDMDevice **)&pIDevice, &ulNumFetched); 146 while (SUCCEEDED(hr) && (hr != S_FALSE)) { 147 /* output device name */ 148 hr = pIDevice->GetName(pwsString, 256); 149 if SUCCEEDED(hr) { 150 wcsncpy_s(name, 256, pwsString, _TRUNCATE); 151 num++; 152 } 153 /* device manufacturer */ 154 hr = pIDevice->GetManufacturer(pwsString, 256); 155 if SUCCEEDED(hr) { 156 wcsncpy_s(manufacturer, 256, pwsString, _TRUNCATE); 157 } 158 /* device version -- optional interface so might fail. */ 159 DWORD ver; 160 hr = pIDevice->GetVersion(&ver); 161 if SUCCEEDED(hr) { 162 *version = ver; 163 } 164 else { 165 *version = 0; 166 } 167 168 /* move to next device */ 169 hr = pIEnumDev->Next(1, (IWMDMDevice **)&pIDevice, &ulNumFetched); 170 } 171 pIEnumDev->Release(); 172 } 173 mtp_close(&mtp); 174 } 175 return (num > 0) ? num : -1; 176} 177 178MTP_DLL_API int mtp_sendnk(LPWSTR file, int filesize, void (*callback)(unsigned int progress, unsigned int max)) 179{ 180 HRESULT hr; 181 bool return_value = false; 182 struct mtp_if mtp; 183 /* zero mtp structure */ 184 memset(&mtp, 0, sizeof(struct mtp_if)); 185 186 /* initialize interface */ 187 mtp_init(&mtp); 188 if(mtp.initialized == false) { 189 return false; 190 } 191 /* enumerate devices... */ 192 IWMDMEnumDevice *pIEnumDev; 193 hr = mtp.pIdvMgr->EnumDevices2(&pIEnumDev); 194 if SUCCEEDED(hr) 195 { 196 hr = pIEnumDev->Reset(); /* Next will now return the first device */ 197 if SUCCEEDED(hr) 198 { 199 IWMDMDevice3* pIDevice; 200 unsigned long ulNumFetched; 201 hr = pIEnumDev->Next(1, (IWMDMDevice **)&pIDevice, &ulNumFetched); 202 while (SUCCEEDED(hr) && (hr != S_FALSE)) 203 { 204 /* get storage info */ 205 DWORD tempDW; 206 pIDevice->GetType(&tempDW); 207 if (tempDW & WMDM_DEVICE_TYPE_STORAGE) 208 { 209 IWMDMEnumStorage *pIEnumStorage = NULL; 210 IWMDMStorage *pIStorage = NULL; 211 IWMDMStorage3 *pIFileStorage = NULL; 212 hr = pIDevice->EnumStorage(&pIEnumStorage); 213 if SUCCEEDED(hr) 214 { 215 pIEnumStorage->Reset(); 216 hr = pIEnumStorage->Next(1, (IWMDMStorage **)&pIStorage, &ulNumFetched); 217 while (SUCCEEDED(hr) && (hr != S_FALSE)) 218 { 219 IWMDMStorage3 *pNewStorage; 220 hr = pIStorage->QueryInterface(IID_IWMDMStorage3, (void **)&pNewStorage); 221 if SUCCEEDED(hr) 222 { 223 IWMDMStorageControl3 *pIWMDMStorageControl; 224 hr = pNewStorage->QueryInterface(IID_IWMDMStorageControl3, 225 (void**)&pIWMDMStorageControl); 226 if SUCCEEDED(hr) 227 { 228 IWMDMMetaData *pIWMDMMetaData = NULL; 229 hr = pNewStorage->CreateEmptyMetadataObject(&pIWMDMMetaData); 230 if (SUCCEEDED(hr)) 231 { 232 DWORD dw = WMDM_FORMATCODE_UNDEFINEDFIRMWARE; 233 hr = pIWMDMMetaData->AddItem(WMDM_TYPE_DWORD, g_wszWMDMFormatCode, (BYTE *)&dw, sizeof(dw)); 234 hr = pIWMDMMetaData->AddItem(WMDM_TYPE_STRING, g_wszWMDMFileName, (BYTE *)L"nk.bin", 32); 235 DWORD ow[2]; 236 ow[0] = filesize; 237 ow[1] = 0; 238 hr = pIWMDMMetaData->AddItem(WMDM_TYPE_QWORD, g_wszWMDMFileSize, (BYTE *)ow, 2 * sizeof(dw)); 239 if (SUCCEEDED(hr)) 240 { 241 IWMDMStorage *pNewObject = NULL; 242 CProgressHelper *progress = new CProgressHelper(callback); 243 244 hr = pIWMDMStorageControl->Insert3( 245 WMDM_MODE_BLOCK | WMDM_CONTENT_FILE | WMDM_MODE_PROGRESS, 246 0, 247 file, 248 NULL, 249 NULL, 250 (callback == NULL ? NULL : (IWMDMProgress*)progress), 251 pIWMDMMetaData, 252 NULL, 253 (IWMDMStorage **)&pNewObject); 254 255 if(SUCCEEDED(hr) 256 || hr == WMDM_S_NOT_ALL_PROPERTIES_APPLIED 257 || hr == WMDM_S_NOT_ALL_PROPERTIES_RETRIEVED) 258 { 259 return_value = true; 260 hr = S_FALSE; 261 } 262 } 263 } 264 } 265 } 266 } 267 } 268 pIEnumStorage->Release(); 269 } 270 271 /* move to next device */ 272 if(!return_value) 273 hr = pIEnumDev->Next(1, (IWMDMDevice **)&pIDevice, &ulNumFetched); 274 } 275 pIEnumDev->Release(); 276 } 277 mtp_close(&mtp); 278 } 279 return return_value ? 1 : 0; 280} 281 282}