Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

362 lines
11 KiB

  1. //
  2. // Microsoft Windows Media Technologies
  3. // Copyright (C) Microsoft Corporation, 1999 - 2001. All rights reserved.
  4. //
  5. // MSHDSP.DLL is a sample WMDM Service Provider(SP) that enumerates fixed drives.
  6. // This sample shows you how to implement an SP according to the WMDM documentation.
  7. // This sample uses fixed drives on your PC to emulate portable media, and
  8. // shows the relationship between different interfaces and objects. Each hard disk
  9. // volume is enumerated as a device and directories and files are enumerated as
  10. // Storage objects under respective devices. You can copy non-SDMI compliant content
  11. // to any device that this SP enumerates. To copy an SDMI compliant content to a
  12. // device, the device must be able to report a hardware embedded serial number.
  13. // Hard disks do not have such serial numbers.
  14. //
  15. // To build this SP, you are recommended to use the MSHDSP.DSP file under Microsoft
  16. // Visual C++ 6.0 and run REGSVR32.EXE to register the resulting MSHDSP.DLL. You can
  17. // then build the sample application from the WMDMAPP directory to see how it gets
  18. // loaded by the application. However, you need to obtain a certificate from
  19. // Microsoft to actually run this SP. This certificate would be in the KEY.C file
  20. // under the INCLUDE directory for one level up.
  21. // MDSPEnumStorage.cpp : Implementation of CMDSPEnumStorage
  22. #include "hdspPCH.h"
  23. #include "wmsstd.h"
  24. #define STRSAFE_NO_DEPRECATE
  25. #include "strsafe.h"
  26. /////////////////////////////////////////////////////////////////////////////
  27. // CMDSPEnumStorage
  28. CMDSPEnumStorage::CMDSPEnumStorage()
  29. {
  30. m_hFFile = INVALID_HANDLE_VALUE;
  31. m_nEndSearch = 0;
  32. m_wcsPath[0] = 0;
  33. }
  34. CMDSPEnumStorage::~CMDSPEnumStorage()
  35. {
  36. if( m_hFFile != INVALID_HANDLE_VALUE )
  37. {
  38. FindClose(m_hFFile);
  39. }
  40. }
  41. STDMETHODIMP CMDSPEnumStorage::Next(ULONG celt, IMDSPStorage **ppStorage, ULONG *pceltFetched)
  42. {
  43. HRESULT hr = S_FALSE;
  44. CARg(ppStorage);
  45. CARg(pceltFetched);
  46. *pceltFetched = 0;
  47. if( m_nEndSearch )
  48. {
  49. return S_FALSE;
  50. }
  51. DWORD dwLen = wcslen(m_wcsPath);
  52. if (dwLen == 0 || dwLen >= ARRAYSIZE(m_wcsPath))
  53. {
  54. // a) Code below aassumes that dwLen > 0 (uses dwLen - 1 as an index
  55. // b) dwLen >= ARRAYSIZE(m_wcsPath) implies m_wcsPath has overflowed
  56. // Below, we use the fact that dwLen < ARRAYSIZE(m_wcsPath) to
  57. // bound the sizes of temp variables into which m_wcsPath is copied
  58. return E_FAIL;
  59. }
  60. if( dwLen < 3 )
  61. {
  62. // For the root storage
  63. CComObject<CMDSPStorage> *pStg;
  64. hr=CComObject<CMDSPStorage>::CreateInstance(&pStg);
  65. if( SUCCEEDED(hr) )
  66. {
  67. hr = pStg->QueryInterface(
  68. IID_IMDSPStorage,
  69. reinterpret_cast<void**>(ppStorage)
  70. );
  71. if( FAILED(hr) )
  72. {
  73. delete pStg;
  74. *pceltFetched = 0;
  75. }
  76. else
  77. {
  78. wcscpy(pStg->m_wcsName, m_wcsPath);
  79. if( m_wcsPath[dwLen-1] != 0x5c )
  80. {
  81. wcscat(pStg->m_wcsName, g_wcsBackslash);
  82. }
  83. m_nEndSearch = 1; // Signal end of enumeration
  84. }
  85. }
  86. if( SUCCEEDED(hr) ) // if obj created successfully
  87. {
  88. *pceltFetched = 1;
  89. if( celt != 1 )
  90. {
  91. hr = S_FALSE; // didn't get what he wanted
  92. }
  93. }
  94. }
  95. else
  96. {
  97. // For non-root storage
  98. WCHAR wcsTmp[MAX_PATH+1+BACKSLASH_STRING_LENGTH];// for appending "\\*"
  99. // Note that ARRAYSIZE(m_wcsPath) == MAX_PATH
  100. char szTmp[MAX_PATH];
  101. WIN32_FIND_DATAA fd;
  102. ULONG i;
  103. for(i=0; (i<celt)&&(!m_nEndSearch); )
  104. {
  105. if( m_hFFile == INVALID_HANDLE_VALUE )
  106. {
  107. wcscpy(wcsTmp, m_wcsPath);
  108. if( m_wcsPath[wcslen(m_wcsPath)-1] != 0x5c )
  109. {
  110. wcscat(wcsTmp, g_wcsBackslash);
  111. }
  112. wcscat(wcsTmp, L"*");
  113. WideCharToMultiByte(CP_ACP, NULL, wcsTmp, -1, szTmp, MAX_PATH, NULL, NULL);
  114. m_hFFile = FindFirstFileA(szTmp, &fd);
  115. if( m_hFFile == INVALID_HANDLE_VALUE )
  116. {
  117. m_nEndSearch = 1;
  118. }
  119. }
  120. else
  121. {
  122. if( !FindNextFileA(m_hFFile, &fd) )
  123. {
  124. m_nEndSearch = 1;
  125. }
  126. }
  127. if ( !m_nEndSearch )
  128. {
  129. if( !strcmp(fd.cFileName, ".") || !strcmp(fd.cFileName, "..") )
  130. {
  131. continue;
  132. }
  133. CComObject<CMDSPStorage> *pStg;
  134. hr = CComObject<CMDSPStorage>::CreateInstance(&pStg);
  135. if( SUCCEEDED(hr) )
  136. {
  137. hr = pStg->QueryInterface(
  138. IID_IMDSPStorage,
  139. reinterpret_cast<void**>(&(ppStorage[*pceltFetched]))
  140. );
  141. if( FAILED(hr) )
  142. {
  143. delete pStg;
  144. break;
  145. }
  146. else
  147. {
  148. // Compute the number of chars we'll use
  149. // up in pStg->m_wcsName
  150. int nHave = ARRAYSIZE(pStg->m_wcsName) - 1;
  151. // -1 for the NULL terminator
  152. nHave -= dwLen;
  153. if( m_wcsPath[dwLen-1] != 0x5c )
  154. {
  155. nHave -= BACKSLASH_STRING_LENGTH;
  156. }
  157. MultiByteToWideChar(CP_ACP, NULL, fd.cFileName, -1, wcsTmp, MAX_PATH);
  158. nHave -= wcslen(wcsTmp);
  159. if (nHave >= 0)
  160. {
  161. wcscpy(pStg->m_wcsName, m_wcsPath);
  162. if( m_wcsPath[dwLen-1] != 0x5c )
  163. {
  164. wcscat(pStg->m_wcsName, g_wcsBackslash);
  165. }
  166. wcscat(pStg->m_wcsName, wcsTmp);
  167. *pceltFetched = (*pceltFetched)+1;
  168. i++;
  169. }
  170. else
  171. {
  172. ppStorage[*pceltFetched]->Release();
  173. ppStorage[*pceltFetched] = NULL;
  174. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  175. //defined in strsafe.h
  176. break;
  177. }
  178. }
  179. }
  180. else
  181. {
  182. break;
  183. }
  184. }
  185. } // end of For loop
  186. if( SUCCEEDED(hr) && (*pceltFetched < celt) )
  187. {
  188. hr = S_FALSE;
  189. }
  190. else if (FAILED(hr))
  191. {
  192. for (; *pceltFetched; )
  193. {
  194. (*pceltFetched)--;
  195. ppStorage[*pceltFetched]->Release();
  196. ppStorage[*pceltFetched] = NULL;
  197. }
  198. }
  199. }
  200. Error:
  201. hrLogDWORD("IMDSPEnumStorage::Next returned 0x%08lx", hr, hr);
  202. return hr;
  203. }
  204. STDMETHODIMP CMDSPEnumStorage::Skip(ULONG celt, ULONG *pceltFetched)
  205. {
  206. HRESULT hr = S_OK;
  207. char szTmp[MAX_PATH];
  208. WCHAR wcsTmp[MAX_PATH+1+BACKSLASH_STRING_LENGTH]; // for appending "\\*"
  209. WIN32_FIND_DATAA fd;
  210. ULONG i;
  211. CARg(celt);
  212. CARg(pceltFetched);
  213. CFRg(!m_nEndSearch); // make sure it is not the end of list
  214. *pceltFetched = 0;
  215. if( wcslen(m_wcsPath) < 3 ) // do nothing if it is the root storage
  216. {
  217. return S_OK;
  218. }
  219. if( wcslen(m_wcsPath) >= ARRAYSIZE(wcsTmp) - BACKSLASH_STRING_LENGTH - 1 )
  220. {
  221. // We check the length against wcsTmp's size because wcsTmp is the
  222. // recipient of a string copy below. However, note that m_wcsPath
  223. // also has MAX_PATH characters, so if this happens, it means that
  224. // it has overflowed. Bail out.
  225. return E_FAIL;
  226. }
  227. for(i=0; (i<celt)&&(!m_nEndSearch); )
  228. {
  229. if( m_hFFile==INVALID_HANDLE_VALUE ) // at the start
  230. {
  231. wcscpy(wcsTmp, m_wcsPath);
  232. if( m_wcsPath[wcslen(m_wcsPath)-1] != 0x5c )
  233. {
  234. wcscat(wcsTmp, g_wcsBackslash);
  235. }
  236. wcscat(wcsTmp, L"*");
  237. WideCharToMultiByte(CP_ACP, NULL, wcsTmp, -1, szTmp, MAX_PATH, NULL, NULL);
  238. m_hFFile = FindFirstFileA(szTmp, &fd);
  239. if( m_hFFile == INVALID_HANDLE_VALUE )
  240. {
  241. m_nEndSearch = 1;
  242. }
  243. }
  244. else
  245. {
  246. if( !FindNextFileA(m_hFFile, &fd) )
  247. {
  248. m_nEndSearch = 1;
  249. }
  250. }
  251. if( !m_nEndSearch )
  252. {
  253. if( !strcmp(fd.cFileName, ".") || !strcmp(fd.cFileName, "..") )
  254. {
  255. continue;
  256. }
  257. *pceltFetched = (*pceltFetched)+1;
  258. i++;
  259. }
  260. }
  261. if( *pceltFetched < celt )
  262. {
  263. hr = S_FALSE;
  264. }
  265. Error:
  266. hrLogDWORD("IMDSPEnumStorage::Skip returned 0x%08lx", hr, hr);
  267. return hr;
  268. }
  269. STDMETHODIMP CMDSPEnumStorage::Reset()
  270. {
  271. HRESULT hr = S_OK;
  272. m_nEndSearch = 0;
  273. if(m_hFFile && m_hFFile != INVALID_HANDLE_VALUE )
  274. {
  275. FindClose(m_hFFile);
  276. }
  277. m_hFFile = INVALID_HANDLE_VALUE;
  278. hrLogDWORD("IMDSPEnumStorage::Reset returned 0x%08lx", hr, hr);
  279. return hr;
  280. }
  281. STDMETHODIMP CMDSPEnumStorage::Clone(IMDSPEnumStorage * * ppEnumStorage)
  282. {
  283. HRESULT hr;
  284. CARg(ppEnumStorage);
  285. CComObject<CMDSPEnumStorage> *pEnumObj;
  286. CORg(CComObject<CMDSPEnumStorage>::CreateInstance(&pEnumObj));
  287. hr = pEnumObj->QueryInterface(
  288. IID_IMDSPEnumStorage,
  289. reinterpret_cast<void**>(ppEnumStorage)
  290. );
  291. if( FAILED(hr) )
  292. {
  293. delete pEnumObj;
  294. }
  295. else
  296. {
  297. // wcscpy(pEnumObj->m_wcsPath, m_wcsPath);
  298. hr = StringCbCopyW(pEnumObj->m_wcsPath,
  299. ARRAYSIZE(pEnumObj->m_wcsPath),
  300. m_wcsPath);
  301. if (FAILED(hr))
  302. {
  303. (*ppEnumStorage)->Release();
  304. *ppEnumStorage = NULL;
  305. goto Error;
  306. }
  307. // @@@@ Not doing anything more is wrong. If m_hFFile is not
  308. // INVALID_HANDLE_VALUE, we have to "advance" the m_hFFile to
  309. // the same extent in the cloned object.
  310. }
  311. Error:
  312. hrLogDWORD("IMDSPEnumStorage::Clone returned 0x%08lx", hr, hr);
  313. return hr;
  314. }