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.

657 lines
18 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  5. //
  6. // File: layscrpt.cxx
  7. //
  8. // Contents: Code for the LayoutScript method
  9. //
  10. //
  11. // History: 22-Apr-96 SusiA Created
  12. //
  13. //----------------------------------------------------------------------------
  14. #include "layouthd.cxx"
  15. #pragma hdrstop
  16. #include <dirfunc.hxx>
  17. #include "layout.hxx"
  18. #include "laylkb.hxx"
  19. #include "laywrap.hxx"
  20. #define NULL_TERM L'\0'
  21. #define BACKSLASH L'\\'
  22. #define MAX_BUFFER 0x10000
  23. //#define UNIT_TEST
  24. //+---------------------------------------------------------------------------
  25. //
  26. // Function: CLayoutRootStorage::FreeStmList
  27. //
  28. // Synopsis: Free the stream linked list
  29. //
  30. // Arguments: [pStmList] -- Pointer STREAMLIST node
  31. //
  32. //----------------------------------------------------------------------------
  33. void CLayoutRootStorage::FreeStmList( STREAMLIST *pStmList)
  34. {
  35. STREAMLIST *ptmp = pStmList;
  36. while (pStmList)
  37. {
  38. ptmp = pStmList->pnext;
  39. #ifdef UNIT_TEST
  40. wprintf(L"STGTY_STREAM %ls\n", pStmList->pwcsStmName );
  41. #endif
  42. CoTaskMemFree(pStmList->pwcsStmName);
  43. pStmList->pStm->Release();
  44. delete pStmList;
  45. pStmList = ptmp;
  46. }
  47. }
  48. //+---------------------------------------------------------------------------
  49. //
  50. // Function: CLayoutRootStorage::FreeStgList
  51. //
  52. // Synopsis: Free the storage linked list
  53. //
  54. // Arguments: [pStgList] -- Pointer STORAGELIST node
  55. //
  56. //----------------------------------------------------------------------------
  57. void CLayoutRootStorage::FreeStgList( STORAGELIST *pStgList)
  58. {
  59. STORAGELIST *ptmp;
  60. while (pStgList)
  61. {
  62. ptmp = pStgList->pnext;
  63. #ifdef UNIT_TEST
  64. wprintf(L"STGTY_STORAGE %ls\n", pStgList->pwcsStgName );
  65. #endif
  66. CoTaskMemFree(pStgList->pwcsStgName);
  67. pStgList->pStg->Release();
  68. delete pStgList;
  69. pStgList = ptmp;
  70. }
  71. }
  72. //+---------------------------------------------------------------------------
  73. //
  74. // Function: CLayoutRootStorage::ProcessOpen
  75. //
  76. // Synopsis: Open the storage or stream
  77. //
  78. // Arguments: [pwcsElementPathName] -- full "path" name of element to open
  79. // [dwType] STGTY_STORAGE or STGTY_STREAM
  80. // [ppIstgStm] interface pointer to the opened Storage or Stream
  81. // [cOffset] offset of beginning of the read
  82. //
  83. // Returns: Appropriate status code
  84. //
  85. // History: 22-Apr-96 SusiA Created
  86. //
  87. //----------------------------------------------------------------------------
  88. SCODE CLayoutRootStorage::ProcessOpen(OLECHAR *pwcsElementPathName,
  89. DWORD dwType,
  90. void **ppIStgStm,
  91. LARGE_INTEGER cOffset)
  92. {
  93. SCODE sc = S_OK;
  94. IStorage *pStgNew;
  95. IStream *pStmNew;
  96. IStorage *pStg = this;
  97. STORAGELIST *pStgList;
  98. STREAMLIST *pStmList;
  99. OLECHAR *pwcsStg = pwcsElementPathName,
  100. *pwcsTemp = pwcsElementPathName;
  101. OLECHAR *pwcsBuffer;
  102. if ( (!pwcsElementPathName) || (pwcsElementPathName[0] == NULL_TERM))
  103. {
  104. return STG_E_PATHNOTFOUND;
  105. }
  106. // process storage path
  107. while (1)
  108. {
  109. while ((*pwcsTemp) && (*pwcsTemp != BACKSLASH))
  110. {
  111. pwcsTemp++;
  112. }
  113. pwcsBuffer = (OLECHAR *) CoTaskMemAlloc
  114. ((INT)(pwcsTemp - pwcsElementPathName + 1) *
  115. sizeof(OLECHAR) );
  116. if (!pwcsBuffer)
  117. {
  118. return STG_E_INSUFFICIENTMEMORY;
  119. }
  120. lstrcpynW (pwcsBuffer,
  121. pwcsElementPathName,
  122. (INT)(pwcsTemp - pwcsElementPathName + 1));
  123. pwcsBuffer[pwcsTemp - pwcsElementPathName] = NULL_TERM;
  124. if (!(*pwcsTemp))
  125. {
  126. //we are at the end, now handle leaf Storage or stream
  127. break;
  128. }
  129. pStgList = _pStgList;
  130. // see if this storage is already in the list
  131. while (pStgList)
  132. {
  133. if (!(lstrcmpW(pwcsBuffer, pStgList->pwcsStgName )))
  134. {
  135. break;
  136. }
  137. pStgList = pStgList->pnext;
  138. }
  139. if (pStgList)
  140. {
  141. pStgNew = pStgList->pStg;
  142. CoTaskMemFree(pwcsBuffer);
  143. }
  144. else
  145. {
  146. sc = pStg->OpenStorage(pwcsBuffer+(pwcsStg-pwcsElementPathName),
  147. NULL,
  148. STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
  149. NULL,
  150. 0,
  151. &pStgNew);
  152. if (FAILED(sc))
  153. {
  154. CoTaskMemFree(pwcsBuffer);
  155. return sc;
  156. }
  157. // add the storage to the list
  158. pStgList = _pStgList;
  159. if (NULL == (_pStgList = new STORAGELIST))
  160. {
  161. CoTaskMemFree(pwcsBuffer);
  162. pStgNew->Release();
  163. return STG_E_INSUFFICIENTMEMORY;
  164. }
  165. _pStgList->pwcsStgName = pwcsBuffer;
  166. _pStgList->pStg = pStgNew;
  167. _pStgList->pnext = pStgList;
  168. }
  169. pStg = pStgNew;
  170. pwcsStg = ++pwcsTemp;
  171. }
  172. //process leaf storage
  173. if (dwType == STGTY_STORAGE)
  174. {
  175. sc = pStg->OpenStorage(pwcsBuffer+(pwcsStg-pwcsElementPathName),
  176. NULL,
  177. STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
  178. NULL,
  179. 0,
  180. &pStgNew);
  181. if (FAILED(sc))
  182. {
  183. CoTaskMemFree(pwcsBuffer);
  184. return sc;
  185. }
  186. // add the storage to the list
  187. pStgList = _pStgList;
  188. if (NULL == (_pStgList = new STORAGELIST))
  189. {
  190. CoTaskMemFree(pwcsBuffer);
  191. pStgNew->Release();
  192. return STG_E_INSUFFICIENTMEMORY;
  193. }
  194. _pStgList->pwcsStgName = pwcsBuffer;
  195. _pStgList->pStg = pStgNew;
  196. _pStgList->pnext = pStgList;
  197. *ppIStgStm = (void *) pStgNew;
  198. }
  199. //process leaf stream
  200. else
  201. {
  202. sc = pStg->OpenStream(pwcsBuffer+(pwcsStg-pwcsElementPathName),
  203. NULL,
  204. STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
  205. 0,
  206. &pStmNew);
  207. if (FAILED(sc))
  208. {
  209. CoTaskMemFree(pwcsBuffer);
  210. return sc;
  211. }
  212. pStmList = _pStmList;
  213. if (NULL == (_pStmList = new STREAMLIST))
  214. {
  215. CoTaskMemFree(pwcsBuffer);
  216. pStmNew->Release();
  217. return STG_E_INSUFFICIENTMEMORY;
  218. }
  219. _pStmList->pwcsStmName = pwcsBuffer;
  220. _pStmList->pStm = pStmNew;
  221. _pStmList->fDone = FALSE;
  222. _pStmList->cOffset = cOffset;
  223. _pStmList->pnext = pStmList;
  224. *ppIStgStm = (void *) pStmNew;
  225. }
  226. return sc;
  227. }
  228. //+---------------------------------------------------------------------------
  229. //
  230. // Function: CLayoutRootStorage::ProcessItem
  231. //
  232. // Synopsis: Construct an unprocessed script from an app provided script
  233. //
  234. // Arguments: [pLayoutItem] -- Pointer to a StorageLayout element of the array
  235. // [fStmDone] -- indicate whether the stream finished reading
  236. //
  237. // Returns: Appropriate status code
  238. //
  239. // History: 22-Apr-96 SusiA Created
  240. //
  241. //----------------------------------------------------------------------------
  242. SCODE CLayoutRootStorage::ProcessItem( StorageLayout *pLayoutItem, BOOL *fStmDone )
  243. {
  244. SCODE sc = S_OK;
  245. STREAMLIST *pStmList = _pStmList;
  246. STORAGELIST *pStgList = _pStgList;
  247. IStorage *pStgNew;
  248. IStream *pStmNew;
  249. ULARGE_INTEGER libNewPosition;
  250. ULONG cbRead;
  251. BYTE abBuffer[MAX_BUFFER];
  252. BYTE *pb = abBuffer;
  253. BOOL fBigBuffer = FALSE;
  254. *fStmDone = FALSE;
  255. if ((pLayoutItem->cOffset.QuadPart < 0) || (pLayoutItem->cBytes.QuadPart < 0))
  256. {
  257. return STG_E_INVALIDPARAMETER;
  258. }
  259. switch (pLayoutItem->LayoutType)
  260. {
  261. case STGTY_STORAGE:
  262. #ifdef UNIT_TEST
  263. wprintf(L"STGTY_STORAGE %ls %lu%lu %lu%lu\n",
  264. pLayoutItem->pwcsElementName,
  265. pLayoutItem->cOffset.HighPart,
  266. pLayoutItem->cOffset.LowPart,
  267. pLayoutItem->cBytes.HighPart,
  268. pLayoutItem->cBytes.LowPart);
  269. #endif
  270. while (pStgList)
  271. {
  272. if (!(lstrcmpW(pLayoutItem->pwcsElementName,
  273. pStgList->pwcsStgName )))
  274. {
  275. break;
  276. }
  277. pStgList = pStgList->pnext;
  278. }
  279. // if storage was not found in the list, open the storage
  280. // and add it to the list
  281. if (!pStgList)
  282. {
  283. sc = ProcessOpen(pLayoutItem->pwcsElementName,
  284. STGTY_STORAGE,
  285. (void **)&pStgNew,
  286. pLayoutItem->cOffset);
  287. if (FAILED(sc))
  288. {
  289. // the application may try to open Storages
  290. // that do not really exist in the compound file,
  291. // and we will let them try.
  292. if (sc == STG_E_FILENOTFOUND)
  293. {
  294. return S_OK;
  295. }
  296. else
  297. {
  298. return sc;
  299. }
  300. }
  301. }
  302. break;
  303. case STGTY_STREAM:
  304. #ifdef UNIT_TEST
  305. wprintf(L"STGTY_STREAM %ls %lu%lu %lu%lu\n",
  306. pLayoutItem->pwcsElementName,
  307. pLayoutItem->cOffset.HighPart,
  308. pLayoutItem->cOffset.LowPart,
  309. pLayoutItem->cBytes.HighPart,
  310. pLayoutItem->cBytes.LowPart);
  311. #endif
  312. while (pStmList)
  313. {
  314. if (!(lstrcmpW(pLayoutItem->pwcsElementName,
  315. pStmList->pwcsStmName )))
  316. {
  317. pStmNew = pStmList->pStm;
  318. break;
  319. }
  320. pStmList = pStmList->pnext;
  321. }
  322. // if stream was not found in the list, open the stream,
  323. // and add it to the list
  324. if (pStmList)
  325. {
  326. if( pStmList->fDone )
  327. {
  328. *fStmDone = TRUE;
  329. return S_OK;
  330. }
  331. }
  332. else
  333. {
  334. sc = ProcessOpen(pLayoutItem->pwcsElementName,
  335. STGTY_STREAM,
  336. (void **)&pStmNew,
  337. pLayoutItem->cOffset);
  338. if (FAILED(sc))
  339. {
  340. // the application may try to open Streams
  341. // that do not really exist in the compound file,
  342. // and we will let them try.
  343. if (sc == STG_E_FILENOTFOUND)
  344. {
  345. return S_OK;
  346. }
  347. else
  348. {
  349. return sc;
  350. }
  351. }
  352. pStmList = _pStmList;
  353. }
  354. // seek to the correct position
  355. sc = pStmNew->Seek(
  356. pStmList->cOffset,
  357. STREAM_SEEK_SET,
  358. &libNewPosition );
  359. if (FAILED(sc))
  360. {
  361. return sc;
  362. }
  363. // read the stream and update the script information
  364. if (pLayoutItem->cBytes.LowPart > MAX_BUFFER)
  365. {
  366. if (NULL == (pb = (BYTE *) CoTaskMemAlloc(pLayoutItem->cBytes.LowPart)) )
  367. {
  368. return STG_E_INSUFFICIENTMEMORY;
  369. }
  370. fBigBuffer = TRUE;
  371. }
  372. sc = pStmNew->Read(pb,
  373. pLayoutItem->cBytes.LowPart,
  374. &cbRead);
  375. if (fBigBuffer)
  376. {
  377. CoTaskMemFree(pb);
  378. fBigBuffer = FALSE;
  379. pb = abBuffer;
  380. }
  381. if (FAILED(sc))
  382. {
  383. return sc;
  384. }
  385. //we have reached the end of the stream, mark it as done
  386. if (cbRead < pLayoutItem->cBytes.LowPart)
  387. {
  388. pStmList->fDone = TRUE;
  389. }
  390. pStmList->cOffset.QuadPart += cbRead;
  391. break;
  392. default:
  393. // we just handle storages and stream types
  394. return STG_E_INVALIDPARAMETER;
  395. }
  396. return sc;
  397. }
  398. //+---------------------------------------------------------------------------
  399. //
  400. // Function: CLayoutRootStorage::ProcessRepeatLoop
  401. //
  402. // Synopsis: Construct an unprocessed script from an app provided script
  403. //
  404. // Arguments: [pStorageLayout] -- Pointer to storage layout array
  405. // [nEntries] -- Number of entries in the array
  406. // [nRepeatStart] -- address of index of start of repeat loop
  407. //
  408. // Returns: Appropriate status code
  409. //
  410. // History: 22-Apr-96 SusiA Created
  411. //
  412. //----------------------------------------------------------------------------
  413. SCODE CLayoutRootStorage::ProcessRepeatLoop( StorageLayout *pStorageLayout,
  414. DWORD nEntries,
  415. int * nRepeatStart)
  416. {
  417. SCODE sc = S_OK;
  418. int i,
  419. nLoopCount = 0,
  420. nLoopTimes;
  421. BOOL fDone = FALSE,
  422. fUntilDone;
  423. // Are we going to repeat until all streams are read to the end?
  424. if ((nLoopTimes = (LONG) pStorageLayout[*nRepeatStart].cBytes.LowPart) != STG_TOEND)
  425. fUntilDone = FALSE;
  426. else
  427. {
  428. fUntilDone = TRUE;
  429. nLoopTimes = 1;
  430. }
  431. // finished when all streams are completely read, or we have
  432. // looped through the specified amount of times
  433. while ((!fDone)&&(nLoopCount < nLoopTimes))
  434. {
  435. if (!fUntilDone)
  436. nLoopCount ++;
  437. i = *nRepeatStart;
  438. fDone = TRUE;
  439. // STGTY_REPEAT with 0 bytes indicates the end of this repeat block
  440. while (!((pStorageLayout[++i].LayoutType == STGTY_REPEAT ) &&
  441. (pStorageLayout[i].cBytes.QuadPart == 0)) )
  442. {
  443. if (i >= (LONG) nEntries)
  444. {
  445. return E_INVALIDARG;
  446. }
  447. // beginning of another repeat block
  448. if (pStorageLayout[i].LayoutType == STGTY_REPEAT )
  449. {
  450. if ((pStorageLayout[i].pwcsElementName !=NULL) ||
  451. (pStorageLayout[i].cOffset.QuadPart < 0) ||
  452. (pStorageLayout[i].cBytes.QuadPart < 0) )
  453. {
  454. return STG_E_INVALIDPARAMETER;
  455. }
  456. layChk(ProcessRepeatLoop(pStorageLayout,
  457. nEntries,
  458. &i));
  459. }
  460. else
  461. {
  462. layChk(ProcessItem(&(pStorageLayout[i]), &fDone));
  463. }
  464. }
  465. }
  466. *nRepeatStart = i;
  467. Err:
  468. return sc;
  469. }
  470. //+---------------------------------------------------------------------------
  471. //
  472. // Function: CLayoutRootStorage::ProcessLayout
  473. //
  474. // Synopsis: Construct an unprocessed script from an app provided script
  475. //
  476. // Arguments: [pStorageLayout] -- Pointer to storage layout array
  477. // [nEntries] -- Number of entries in the array
  478. // [grfInterleavedFlag] -- Specifies disposition of control
  479. // structures
  480. //
  481. // Returns: Appropriate status code
  482. //
  483. // History: 22-Apr-96 SusiA Created
  484. //
  485. //----------------------------------------------------------------------------
  486. SCODE CLayoutRootStorage::ProcessLayout( StorageLayout *pStorageLayout,
  487. DWORD nEntries,
  488. DWORD glfInterleavedFlag)
  489. {
  490. SCODE sc = S_OK;
  491. int i;
  492. BOOL fUnused;
  493. TCHAR *patcScriptName = _pllkb->GetScriptName();
  494. for (i = 0; i < (LONG) nEntries; i++)
  495. {
  496. if (pStorageLayout[i].LayoutType == STGTY_REPEAT )
  497. {
  498. if (pStorageLayout[i].cBytes.QuadPart != 0)
  499. {
  500. if ((pStorageLayout[i].pwcsElementName !=NULL) ||
  501. (pStorageLayout[i].cOffset.QuadPart < 0) ||
  502. (pStorageLayout[i].cBytes.QuadPart < 0) )
  503. {
  504. return STG_E_INVALIDPARAMETER;
  505. }
  506. layChk(ProcessRepeatLoop(pStorageLayout,
  507. nEntries,
  508. &i));
  509. }
  510. else //end repeat block with no matching beginning
  511. {
  512. sc = E_INVALIDARG;
  513. layChk(sc);
  514. }
  515. }
  516. else // (pStorageLayout[i].LayoutType == STGTY_REPEAT )
  517. {
  518. layChk(ProcessItem(&(pStorageLayout[i]), &fUnused));
  519. }
  520. }
  521. Err:
  522. if (_pStgList)
  523. {
  524. FreeStgList(_pStgList);
  525. _pStgList = NULL;
  526. }
  527. if (_pStmList)
  528. {
  529. FreeStmList(_pStmList);
  530. _pStmList = NULL;
  531. }
  532. return sc;
  533. }