Source code of Windows XP (NT5)
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.

691 lines
18 KiB

  1. //+--------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992.
  5. //
  6. // File: storage.cxx
  7. //
  8. // Contents: Contains generic storage APIs
  9. //
  10. // History: 05-Oct-92 DrewB Created
  11. //
  12. //---------------------------------------------------------------
  13. #include <exphead.cxx>
  14. #pragma hdrstop
  15. #include <dfentry.hxx>
  16. #include <storagep.h>
  17. #include <logfile.hxx>
  18. #include <df32.hxx>
  19. #ifdef COORD
  20. #include <oledb.h>
  21. #endif //COORD
  22. #include <trace.hxx>
  23. #include <ole2sp.h>
  24. #include <ole2com.h>
  25. //+--------------------------------------------------------------
  26. //
  27. // Function: StgOpenStorage, public
  28. //
  29. // Synopsis: Instantiates a root storage from a file
  30. // by binding to the appropriate implementation
  31. // and starting things up
  32. //
  33. // Arguments: [pwcsName] - Name
  34. // [pstgPriority] - Priority mode reopen IStorage
  35. // [grfMode] - Permissions
  36. // [snbExclude] - Exclusions for priority reopen
  37. // [reserved]
  38. // [ppstgOpen] - Docfile return
  39. //
  40. // Returns: Appropriate status code
  41. //
  42. // Modifies: [ppstgOpen]
  43. //
  44. // History: 05-Oct-92 DrewB Created
  45. //
  46. //---------------------------------------------------------------
  47. STDAPI StgOpenStorage(OLECHAR const *pwcsName,
  48. IStorage *pstgPriority,
  49. DWORD grfMode,
  50. SNB snbExclude,
  51. LPSTGSECURITY reserved,
  52. IStorage **ppstgOpen)
  53. {
  54. return DfOpenDocfile(pwcsName, NULL, pstgPriority, grfMode,
  55. snbExclude, reserved, NULL, 0, ppstgOpen);
  56. }
  57. //+---------------------------------------------------------------------------
  58. //
  59. // Function: CheckSignature, private
  60. //
  61. // Synopsis: Checks the given memory against known signatures
  62. //
  63. // Arguments: [pb] - Pointer to memory to check
  64. //
  65. // Returns: S_OK - Current signature
  66. // S_FALSE - Beta 2 signature, but still successful
  67. // Appropriate status code
  68. //
  69. // History: 23-Jul-93 DrewB Created from header.cxx code
  70. //
  71. //----------------------------------------------------------------------------
  72. //Identifier for first bytes of Beta 1 Docfiles
  73. const BYTE SIGSTG_B1[] = {0xd0, 0xcf, 0x11, 0xe0, 0x0e, 0x11, 0xfc, 0x0d};
  74. const USHORT CBSIGSTG_B1 = sizeof(SIGSTG_B1);
  75. //Identifier for first bytes of Beta 2 Docfiles
  76. const BYTE SIGSTG_B2[] = {0x0e, 0x11, 0xfc, 0x0d, 0xd0, 0xcf, 0x11, 0xe0};
  77. const BYTE CBSIGSTG_B2 = sizeof(SIGSTG_B2);
  78. SCODE CheckSignature(BYTE *pb)
  79. {
  80. SCODE sc;
  81. olDebugOut((DEB_ITRACE, "In CheckSignature(%p)\n", pb));
  82. // Check for ship Docfile signature first
  83. if (memcmp(pb, SIGSTG, CBSIGSTG) == 0)
  84. sc = S_OK;
  85. // Check for Beta 2 Docfile signature
  86. else if (memcmp(pb, SIGSTG_B2, CBSIGSTG_B2) == 0)
  87. sc = S_FALSE;
  88. // Check for Beta 1 Docfile signature
  89. else if (memcmp(pb, SIGSTG_B1, CBSIGSTG_B1) == 0)
  90. sc = STG_E_OLDFORMAT;
  91. else
  92. sc = STG_E_INVALIDHEADER;
  93. olDebugOut((DEB_ITRACE, "Out CheckSignature => %lX\n", sc));
  94. return sc;
  95. }
  96. //+--------------------------------------------------------------
  97. //
  98. // Function: StgIsStorageFileHandle, private
  99. //
  100. // Synopsis: Determines whether a handle is open on a storage file.
  101. // Spun off from StgIsStorageFile. Internaly we use this
  102. //
  103. // Arguments: [hf] - Open File Handle (caller must seek it to 0)
  104. //
  105. // Returns: S_OK, S_FALSE or error codes
  106. //
  107. // History: 07-May-98 MikeHill Created
  108. // 05-June-98 BChapman Return Errors not just S_FALSE.
  109. // Add optional Overlapped pointer.
  110. //
  111. //---------------------------------------------------------------
  112. STDAPI StgIsStorageFileHandle( HANDLE hf, LPOVERLAPPED povlp )
  113. {
  114. DWORD cbRead;
  115. BYTE stgHeader[sizeof(SStorageFile)];
  116. SCODE sc;
  117. LONG status;
  118. OVERLAPPED ovlp;
  119. FillMemory( stgHeader, sizeof(SStorageFile), 0xDE );
  120. if (povlp == NULL)
  121. {
  122. ovlp.Offset = 0;
  123. ovlp.OffsetHigh = 0;
  124. ovlp.hEvent = NULL;
  125. }
  126. if( !ReadFile( hf,
  127. &stgHeader,
  128. sizeof( stgHeader ),
  129. &cbRead,
  130. (povlp == NULL) ? &ovlp : povlp ) )
  131. {
  132. if( NULL != povlp )
  133. {
  134. status = GetLastError();
  135. if( ERROR_IO_PENDING == status)
  136. {
  137. status = ERROR_SUCCESS;
  138. if( !GetOverlappedResult( hf, povlp, &cbRead, TRUE ) )
  139. status = GetLastError();
  140. }
  141. if(ERROR_SUCCESS != status && ERROR_HANDLE_EOF != status)
  142. olChk( HRESULT_FROM_WIN32( status ) );
  143. }
  144. else
  145. olErr( EH_Err, S_FALSE );
  146. }
  147. // Don't worry about short reads. If the read is short then
  148. // the signature checks will fail.
  149. sc = CheckSignature( ((SStorageFile*)stgHeader)->abSig );
  150. if(S_OK == sc)
  151. goto EH_Err; // Done, return "Yes"
  152. olChk(sc);
  153. // It didn't error. sc != S_OK then it
  154. // Must be S_FALSE.
  155. olAssert(S_FALSE == sc);
  156. EH_Err:
  157. if( (STG_E_OLDFORMAT == sc) || (STG_E_INVALIDHEADER == sc) )
  158. sc = S_FALSE;
  159. return sc;
  160. }
  161. //+--------------------------------------------------------------
  162. //
  163. // Function: StgIsStorageFile, public
  164. //
  165. // Synopsis: Determines whether the named file is a storage or not
  166. //
  167. // Arguments: [pwcsName] - Filename
  168. //
  169. // Returns: S_OK, S_FALSE or error codes
  170. //
  171. // History: 05-Oct-92 DrewB Created
  172. //
  173. //---------------------------------------------------------------
  174. STDAPI StgIsStorageFile(OLECHAR const *pwcsName)
  175. {
  176. HANDLE hf;
  177. SCODE sc;
  178. olLog(("--------::In StgIsStorageFile(" OLEFMT ")\n", pwcsName));
  179. TRY
  180. {
  181. #ifndef OLEWIDECHAR
  182. if (FAILED(sc = ValidateNameA(pwcsName, _MAX_PATH)))
  183. #else
  184. if (FAILED(sc = ValidateNameW(pwcsName, _MAX_PATH)))
  185. #endif
  186. return ResultFromScode(sc);
  187. #if !defined(UNICODE)
  188. // Chicago - call ANSI CreateFile
  189. char szName[_MAX_PATH + 1];
  190. if (!WideCharToMultiByte(
  191. AreFileApisANSI() ? CP_ACP : CP_OEMCP,
  192. 0,
  193. pwcsName,
  194. -1,
  195. szName,
  196. _MAX_PATH + 1,
  197. NULL,
  198. NULL))
  199. return ResultFromScode(STG_E_INVALIDNAME);
  200. hf = CreateFileA (
  201. szName,
  202. GENERIC_READ,
  203. FILE_SHARE_READ | FILE_SHARE_WRITE,
  204. NULL,
  205. OPEN_EXISTING,
  206. FILE_ATTRIBUTE_NORMAL,
  207. NULL
  208. );
  209. #else
  210. hf = CreateFile (
  211. pwcsName,
  212. GENERIC_READ,
  213. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  214. NULL,
  215. OPEN_EXISTING,
  216. FILE_ATTRIBUTE_NORMAL,
  217. NULL
  218. );
  219. #endif // !defined(UNICODE)
  220. if (hf == INVALID_HANDLE_VALUE)
  221. return ResultFromScode(STG_SCODE(GetLastError()));
  222. sc = StgIsStorageFileHandle( hf, NULL );
  223. CloseHandle (hf);
  224. }
  225. CATCH(CException, e)
  226. {
  227. sc = e.GetErrorCode();
  228. }
  229. END_CATCH
  230. olLog(("--------::Out StgIsStorageFile(). ret == %lx\n", sc));
  231. return(ResultFromScode(sc));
  232. }
  233. //+--------------------------------------------------------------
  234. //
  235. // Function: StgIsStorageILockBytes, public
  236. //
  237. // Synopsis: Determines whether the ILockBytes is a storage or not
  238. //
  239. // Arguments: [plkbyt] - The ILockBytes
  240. //
  241. // Returns: S_OK, S_FALSE or error codes
  242. //
  243. // History: 05-Oct-92 DrewB Created
  244. //
  245. //---------------------------------------------------------------
  246. STDAPI StgIsStorageILockBytes(ILockBytes *plkbyt)
  247. {
  248. OLETRACEIN((API_StgIsStorageILockBytes, PARAMFMT("plkbyt= %p"), plkbyt));
  249. HRESULT hr;
  250. SCODE sc;
  251. SStorageFile stgfile;
  252. ULONG cbRead;
  253. ULARGE_INTEGER ulOffset;
  254. TRY
  255. {
  256. if (FAILED(sc = ValidateInterface(plkbyt, IID_ILockBytes)))
  257. {
  258. hr = ResultFromScode(sc);
  259. goto errRtn;
  260. }
  261. ULISet32(ulOffset, 0);
  262. hr = plkbyt->ReadAt(ulOffset, &stgfile, sizeof(stgfile), &cbRead);
  263. if (FAILED(GetScode(hr)))
  264. {
  265. goto errRtn;
  266. }
  267. }
  268. CATCH(CException, e)
  269. {
  270. hr = ResultFromScode(e.GetErrorCode());
  271. goto errRtn;
  272. }
  273. END_CATCH
  274. if (cbRead == sizeof(stgfile))
  275. {
  276. if ((memcmp((void *)stgfile.abSig, SIGSTG, CBSIGSTG) == 0) ||
  277. (memcmp((void *)stgfile.abSig, SIGSTG_B2, CBSIGSTG_B2) == 0))
  278. {
  279. hr = ResultFromScode(S_OK);
  280. goto errRtn;
  281. }
  282. }
  283. hr = ResultFromScode(S_FALSE);
  284. errRtn:
  285. OLETRACEOUT((API_StgIsStorageILockBytes, hr));
  286. return hr;
  287. }
  288. //+--------------------------------------------------------------
  289. //
  290. // Function: StgSetTimes
  291. //
  292. // Synopsis: Sets file time stamps
  293. //
  294. // Arguments: [lpszName] - Name
  295. // [pctime] - create time
  296. // [patime] - access time
  297. // [pmtime] - modify time
  298. //
  299. // Returns: Appropriate status code
  300. //
  301. // History: 05-Oct-92 AlexT Created
  302. //
  303. //---------------------------------------------------------------
  304. STDAPI StgSetTimes(OLECHAR const *lpszName,
  305. FILETIME const *pctime,
  306. FILETIME const *patime,
  307. FILETIME const *pmtime)
  308. {
  309. SCODE sc;
  310. HANDLE hFile;
  311. TRY
  312. {
  313. #ifndef OLEWIDECHAR
  314. sc = ValidateNameA(lpszName, _MAX_PATH);
  315. #else
  316. sc = ValidateNameW(lpszName, _MAX_PATH);
  317. #endif
  318. if (SUCCEEDED(sc))
  319. {
  320. #if !defined(UNICODE) && defined(OLEWIDECHAR)
  321. //Chicago - call ANSI CreateFile
  322. char szName[_MAX_PATH];
  323. if (!WideCharToMultiByte(
  324. AreFileApisANSI() ? CP_ACP : CP_OEMCP,
  325. 0,
  326. lpszName,
  327. -1,
  328. szName,
  329. _MAX_PATH,
  330. NULL,
  331. NULL))
  332. return ResultFromScode(STG_E_INVALIDNAME);
  333. hFile = CreateFileA(szName, GENERIC_WRITE,
  334. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  335. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
  336. NULL);
  337. #else
  338. hFile = CreateFile(lpszName, GENERIC_WRITE,
  339. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  340. OPEN_EXISTING,
  341. FILE_ATTRIBUTE_NORMAL,
  342. NULL);
  343. #endif
  344. if (hFile == INVALID_HANDLE_VALUE)
  345. sc = LAST_STG_SCODE;
  346. else
  347. {
  348. if (!SetFileTime(hFile, (FILETIME *)pctime, (FILETIME *)patime,
  349. (FILETIME *)pmtime))
  350. sc = LAST_STG_SCODE;
  351. CloseHandle(hFile);
  352. }
  353. }
  354. }
  355. CATCH(CException, e)
  356. {
  357. sc = e.GetErrorCode();
  358. }
  359. END_CATCH
  360. return ResultFromScode(sc);
  361. }
  362. #if DBG==1
  363. extern "C" unsigned long filestInfoLevel; // File I/O layer of Docfile
  364. extern "C" unsigned long nffInfoLevel; // NTFS Flat File
  365. void
  366. StgDebugInit()
  367. {
  368. GetInfoLevel("filest", &filestInfoLevel, "0x0003");
  369. GetInfoLevel( "nff", &nffInfoLevel, "0x0003");
  370. }
  371. #endif // DBG==1
  372. //+---------------------------------------------------------------------------
  373. //
  374. // Function: NormalDllGetClassObject, public
  375. //
  376. // Synopsis: Registers any normal Inproc Dll server.
  377. //
  378. // Arguments: [refCLSID] Class ID of object to register
  379. // [pwszDescription] Description to put in the CLSID Key
  380. // [pwszDllName] Dll where the object's code lives
  381. // [pwszThreadingModel] Threading Model (i.e. L"both")
  382. //
  383. // Returns: Appropriate status code
  384. //
  385. // History: 15-jan-98 BChapman Created
  386. //
  387. //----------------------------------------------------------------------------
  388. #define STRBUFSZ 64
  389. STDAPI NormalDllRegisterServer(
  390. REFCLSID refCLSID,
  391. WCHAR * pwszDescription,
  392. WCHAR * pwszDllName,
  393. WCHAR * pwszThreadingModel)
  394. {
  395. HKEY hkeyCLSID=NULL;
  396. HKEY hkeyInproc32=NULL;
  397. DWORD dwDisp=0;
  398. LONG rc;
  399. HRESULT sc=S_OK;
  400. WCHAR wszCLSID[STRBUFSZ];
  401. WCHAR wszCLSKey[STRBUFSZ];
  402. //--------------------------------------
  403. // Construct and Open the Class ID key.
  404. //
  405. if(0 == StringFromGUID2(refCLSID, wszCLSID, STRBUFSZ))
  406. olErr( EH_Err, E_UNEXPECTED );
  407. wcscpy(wszCLSKey, L"CLSID\\");
  408. wcscat(wszCLSKey, wszCLSID);
  409. rc = RegCreateKeyEx(HKEY_CLASSES_ROOT, wszCLSKey,
  410. 0, _T(""), REG_OPTION_NON_VOLATILE,
  411. KEY_WRITE, NULL,
  412. &hkeyCLSID, &dwDisp);
  413. if(ERROR_SUCCESS != rc)
  414. olErr( EH_Err, REGDB_E_WRITEREGDB );
  415. //-----------------------------------------------------
  416. // Set the description string on the Class ID Key
  417. //
  418. rc = RegSetValueEx(hkeyCLSID, _T(""), 0,
  419. REG_SZ, (BYTE*) pwszDescription,
  420. sizeof(WCHAR)*(1+wcslen(pwszDescription)) );
  421. if(ERROR_SUCCESS != rc)
  422. olErr( EH_Err, REGDB_E_WRITEREGDB );
  423. //---------------------------
  424. // Open the Inproc32 Sub-key.
  425. //
  426. rc = RegCreateKeyEx(hkeyCLSID, _T("InprocServer32"),
  427. 0, _T(""), REG_OPTION_NON_VOLATILE,
  428. KEY_WRITE, NULL,
  429. &hkeyInproc32, &dwDisp);
  430. if(ERROR_SUCCESS != rc)
  431. olErr( EH_Err, REGDB_E_WRITEREGDB );
  432. //-----------------------------------------
  433. // Set the DLL name on the Inproc32 Sub-Key
  434. //
  435. rc = RegSetValueEx(hkeyInproc32, _T(""), 0,
  436. REG_SZ, (BYTE*) pwszDllName,
  437. sizeof(WCHAR)*(1+wcslen(pwszDllName)));
  438. if(ERROR_SUCCESS != rc)
  439. olErr( EH_Err, REGDB_E_WRITEREGDB );
  440. //------------------------
  441. // Set the Threading Model
  442. //
  443. rc = RegSetValueEx(hkeyInproc32, _T("ThreadingModel"), 0,
  444. REG_SZ, (BYTE*) pwszThreadingModel,
  445. sizeof(WCHAR)*(1+wcslen(pwszThreadingModel)));
  446. if(ERROR_SUCCESS != rc)
  447. olErr( EH_Err, REGDB_E_WRITEREGDB );
  448. EH_Err:
  449. if(NULL != hkeyCLSID)
  450. RegCloseKey(hkeyCLSID);
  451. if(NULL != hkeyInproc32)
  452. RegCloseKey(hkeyInproc32);
  453. return sc;
  454. }
  455. //+---------------------------------------------------------------------------
  456. //
  457. // Function: AddCLSIDToMultiSz, public
  458. //
  459. // Synopsis: Add the string form of a Class ID to a MultiSZ registry value.
  460. //
  461. // Arguments: [refCLSID] Class ID to register
  462. // [hkeyStart] An open registry key.
  463. // [wcszKey] Path to the key reletive to hkeyStart.
  464. // [wcszValue] Name of the Value under wcszKey.
  465. //
  466. // Returns: Appropriate status code
  467. //
  468. // History: 18-jan-98 BChapman Created
  469. //
  470. //----------------------------------------------------------------------------
  471. STDAPI AddCLSIDToMultiSz(
  472. REFCLSID refCLSID,
  473. HKEY hkeyStart,
  474. WCHAR* wcszKey,
  475. WCHAR* wcszValue)
  476. {
  477. WCHAR wszCLSID[STRBUFSZ];
  478. int ccCLSIDstr;
  479. LONG rc;
  480. HRESULT sc=S_OK;
  481. HKEY hkeyKey=NULL;
  482. BYTE* p_bytes=NULL;
  483. WCHAR* p_wsz=NULL;
  484. DWORD cbData, cbDataNew;
  485. DWORD dwType;
  486. ccCLSIDstr = StringFromGUID2( refCLSID, wszCLSID, STRBUFSZ );
  487. if( 0 == ccCLSIDstr )
  488. olErr( EH_Err, E_UNEXPECTED );
  489. ccCLSIDstr += 1; // +1 for the NULL
  490. // Open the Key
  491. //
  492. rc = RegOpenKeyEx(hkeyStart,
  493. wcszKey,
  494. 0,
  495. KEY_QUERY_VALUE | KEY_SET_VALUE,
  496. &hkeyKey);
  497. if( ERROR_SUCCESS != rc )
  498. olErr( EH_Err, REGDB_E_KEYMISSING );
  499. // Size The Buffer,
  500. // Allocate the buffer,
  501. // And Read the data.
  502. //
  503. cbData = 0;
  504. cbDataNew = 0;
  505. rc = RegQueryValueEx( hkeyKey,
  506. wcszValue,
  507. 0,
  508. &dwType,
  509. NULL,
  510. &cbData );
  511. if( ERROR_SUCCESS != rc )
  512. {
  513. //
  514. // The value may not exist. In that case we make a new entry.
  515. // Rather than depend on an exact error code, lets take the "new"
  516. // path on all failures. We will hit real problems in the "write"
  517. // phase
  518. cbData = 1*sizeof(WCHAR); // +1 for the terminating second Null.
  519. cbDataNew = (ccCLSIDstr + 1) * sizeof(WCHAR);
  520. olMem( p_bytes = new BYTE[ cbDataNew ] );
  521. memset( p_bytes, 0, cbDataNew );
  522. }
  523. else
  524. {
  525. if( REG_MULTI_SZ != dwType )
  526. olErr( EH_Err, REGDB_E_INVALIDVALUE );
  527. // cbData is in units of bytes
  528. //
  529. cbDataNew = cbData + ( ccCLSIDstr * sizeof(WCHAR) );
  530. olMem( p_bytes = new BYTE[ cbDataNew ] );
  531. memset( p_bytes, 0, cbDataNew );
  532. rc = RegQueryValueEx( hkeyKey,
  533. wcszValue,
  534. 0,
  535. &dwType,
  536. p_bytes,
  537. &cbData );
  538. if( ERROR_SUCCESS != rc )
  539. olErr( EH_Err, LAST_SCODE );
  540. }
  541. // Check if the Class Id is already present
  542. //
  543. p_wsz = (WCHAR*)p_bytes;
  544. while( L'\0' != *p_wsz)
  545. {
  546. if( 0 == wcscmp( p_wsz, wszCLSID ) )
  547. break;
  548. // Advance to the end of the String.
  549. while( L'\0' != *p_wsz)
  550. ++p_wsz;
  551. // Advance to the start of the next String.
  552. // Or the terminating second null.
  553. ++p_wsz;
  554. }
  555. // If the Class Id is not already present,
  556. // Add the Class Id to the list
  557. // And write it into the Registry
  558. //
  559. if( L'\0' == *p_wsz )
  560. {
  561. wcscpy( p_wsz, wszCLSID );
  562. p_wsz[ ccCLSIDstr ] = L'\0'; // Add the Second Null.
  563. rc = RegSetValueEx( hkeyKey,
  564. wcszValue,
  565. 0,
  566. REG_MULTI_SZ,
  567. p_bytes,
  568. cbDataNew );
  569. if( ERROR_SUCCESS != rc )
  570. olErr( EH_Err, REGDB_E_WRITEREGDB );
  571. }
  572. EH_Err:
  573. if( NULL != hkeyKey )
  574. RegCloseKey( hkeyKey );
  575. if( NULL != p_bytes )
  576. delete[] p_bytes;
  577. return sc;
  578. }
  579. //+---------------------------------------------------------------------------
  580. //
  581. // Function: DllRegisterServer, public
  582. //
  583. // Returns: Appropriate status code
  584. //
  585. // History: 15-jan-98 BChpaman Created
  586. //
  587. //----------------------------------------------------------------------------
  588. STDAPI Storage32DllRegisterServer(void)
  589. {
  590. HRESULT hrAccum=S_OK;
  591. return hrAccum;
  592. }