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.

646 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. _pStgList = pStgList; // restore the old list
  164. return STG_E_INSUFFICIENTMEMORY;
  165. }
  166. _pStgList->pwcsStgName = pwcsBuffer;
  167. _pStgList->pStg = pStgNew;
  168. _pStgList->pnext = pStgList;
  169. }
  170. pStg = pStgNew;
  171. pwcsStg = ++pwcsTemp;
  172. }
  173. //process leaf storage
  174. if (dwType == STGTY_STORAGE)
  175. {
  176. sc = pStg->OpenStorage(pwcsBuffer+(pwcsStg-pwcsElementPathName),
  177. NULL,
  178. STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
  179. NULL,
  180. 0,
  181. &pStgNew);
  182. if (FAILED(sc))
  183. {
  184. CoTaskMemFree(pwcsBuffer);
  185. return sc;
  186. }
  187. // add the storage to the list
  188. pStgList = _pStgList;
  189. if (NULL == (_pStgList = new STORAGELIST))
  190. {
  191. CoTaskMemFree(pwcsBuffer);
  192. pStgNew->Release();
  193. _pStgList = pStgList; // restore the old list
  194. return STG_E_INSUFFICIENTMEMORY;
  195. }
  196. _pStgList->pwcsStgName = pwcsBuffer;
  197. _pStgList->pStg = pStgNew;
  198. _pStgList->pnext = pStgList;
  199. *ppIStgStm = (void *) pStgNew;
  200. }
  201. //process leaf stream
  202. else
  203. {
  204. sc = pStg->OpenStream(pwcsBuffer+(pwcsStg-pwcsElementPathName),
  205. NULL,
  206. STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
  207. 0,
  208. &pStmNew);
  209. if (FAILED(sc))
  210. {
  211. CoTaskMemFree(pwcsBuffer);
  212. return sc;
  213. }
  214. pStmList = _pStmList;
  215. if (NULL == (_pStmList = new STREAMLIST))
  216. {
  217. CoTaskMemFree(pwcsBuffer);
  218. pStmNew->Release();
  219. _pStmList = pStmList; // restore the old list
  220. return STG_E_INSUFFICIENTMEMORY;
  221. }
  222. _pStmList->pwcsStmName = pwcsBuffer;
  223. _pStmList->pStm = pStmNew;
  224. _pStmList->fDone = FALSE;
  225. _pStmList->cOffset = cOffset;
  226. _pStmList->pnext = pStmList;
  227. *ppIStgStm = (void *) pStmNew;
  228. }
  229. return sc;
  230. }
  231. //+---------------------------------------------------------------------------
  232. //
  233. // Function: CLayoutRootStorage::ProcessItem
  234. //
  235. // Synopsis: Construct an unprocessed script from an app provided script
  236. //
  237. // Arguments: [pLayoutItem] -- Pointer to a StorageLayout element of the array
  238. // [fStmDone] -- indicate whether the stream finished reading
  239. //
  240. // Returns: Appropriate status code
  241. //
  242. // History: 22-Apr-96 SusiA Created
  243. //
  244. //----------------------------------------------------------------------------
  245. SCODE CLayoutRootStorage::ProcessItem( StorageLayout *pLayoutItem, BOOL *fStmDone )
  246. {
  247. SCODE sc = S_OK;
  248. STREAMLIST *pStmList = _pStmList;
  249. STORAGELIST *pStgList = _pStgList;
  250. IStorage *pStgNew;
  251. IStream *pStmNew;
  252. ULARGE_INTEGER libNewPosition;
  253. ULONG cbRead;
  254. BYTE *pb = NULL;
  255. *fStmDone = FALSE;
  256. if ((pLayoutItem->cOffset.QuadPart < 0) || (pLayoutItem->cBytes.QuadPart < 0))
  257. {
  258. return STG_E_INVALIDPARAMETER;
  259. }
  260. switch (pLayoutItem->LayoutType)
  261. {
  262. case STGTY_STORAGE:
  263. #ifdef UNIT_TEST
  264. wprintf(L"STGTY_STORAGE %ls %lu%lu %lu%lu\n",
  265. pLayoutItem->pwcsElementName,
  266. pLayoutItem->cOffset.HighPart,
  267. pLayoutItem->cOffset.LowPart,
  268. pLayoutItem->cBytes.HighPart,
  269. pLayoutItem->cBytes.LowPart);
  270. #endif
  271. while (pStgList)
  272. {
  273. if (!(lstrcmpW(pLayoutItem->pwcsElementName,
  274. pStgList->pwcsStgName )))
  275. {
  276. break;
  277. }
  278. pStgList = pStgList->pnext;
  279. }
  280. // if storage was not found in the list, open the storage
  281. // and add it to the list
  282. if (!pStgList)
  283. {
  284. sc = ProcessOpen(pLayoutItem->pwcsElementName,
  285. STGTY_STORAGE,
  286. (void **)&pStgNew,
  287. pLayoutItem->cOffset);
  288. if (FAILED(sc))
  289. {
  290. // the application may try to open Storages
  291. // that do not really exist in the compound file,
  292. // and we will let them try.
  293. if (sc == STG_E_FILENOTFOUND)
  294. {
  295. return S_OK;
  296. }
  297. else
  298. {
  299. return sc;
  300. }
  301. }
  302. }
  303. break;
  304. case STGTY_STREAM:
  305. #ifdef UNIT_TEST
  306. wprintf(L"STGTY_STREAM %ls %lu%lu %lu%lu\n",
  307. pLayoutItem->pwcsElementName,
  308. pLayoutItem->cOffset.HighPart,
  309. pLayoutItem->cOffset.LowPart,
  310. pLayoutItem->cBytes.HighPart,
  311. pLayoutItem->cBytes.LowPart);
  312. #endif
  313. while (pStmList)
  314. {
  315. if (!(lstrcmpW(pLayoutItem->pwcsElementName,
  316. pStmList->pwcsStmName )))
  317. {
  318. pStmNew = pStmList->pStm;
  319. break;
  320. }
  321. pStmList = pStmList->pnext;
  322. }
  323. // if stream was not found in the list, open the stream,
  324. // and add it to the list
  325. if (pStmList)
  326. {
  327. if( pStmList->fDone )
  328. {
  329. *fStmDone = TRUE;
  330. return S_OK;
  331. }
  332. }
  333. else
  334. {
  335. sc = ProcessOpen(pLayoutItem->pwcsElementName,
  336. STGTY_STREAM,
  337. (void **)&pStmNew,
  338. pLayoutItem->cOffset);
  339. if (FAILED(sc))
  340. {
  341. // the application may try to open Streams
  342. // that do not really exist in the compound file,
  343. // and we will let them try.
  344. if (sc == STG_E_FILENOTFOUND)
  345. {
  346. return S_OK;
  347. }
  348. else
  349. {
  350. return sc;
  351. }
  352. }
  353. pStmList = _pStmList;
  354. }
  355. // seek to the correct position
  356. sc = pStmNew->Seek(
  357. pStmList->cOffset,
  358. STREAM_SEEK_SET,
  359. &libNewPosition );
  360. if (FAILED(sc))
  361. {
  362. return sc;
  363. }
  364. // read the stream and update the script information
  365. if (NULL == (pb = (BYTE *) CoTaskMemAlloc(pLayoutItem->cBytes.LowPart)) )
  366. {
  367. return STG_E_INSUFFICIENTMEMORY;
  368. }
  369. sc = pStmNew->Read(pb,
  370. pLayoutItem->cBytes.LowPart,
  371. &cbRead);
  372. CoTaskMemFree(pb);
  373. pb = NULL;
  374. if (FAILED(sc))
  375. {
  376. return sc;
  377. }
  378. //we have reached the end of the stream, mark it as done
  379. if (cbRead < pLayoutItem->cBytes.LowPart)
  380. {
  381. pStmList->fDone = TRUE;
  382. }
  383. pStmList->cOffset.QuadPart += cbRead;
  384. break;
  385. default:
  386. // we just handle storages and stream types
  387. return STG_E_INVALIDPARAMETER;
  388. }
  389. return sc;
  390. }
  391. //+---------------------------------------------------------------------------
  392. //
  393. // Function: CLayoutRootStorage::ProcessRepeatLoop
  394. //
  395. // Synopsis: Construct an unprocessed script from an app provided script
  396. //
  397. // Arguments: [pStorageLayout] -- Pointer to storage layout array
  398. // [nEntries] -- Number of entries in the array
  399. // [nRepeatStart] -- address of index of start of repeat loop
  400. //
  401. // Returns: Appropriate status code
  402. //
  403. // History: 22-Apr-96 SusiA Created
  404. //
  405. //----------------------------------------------------------------------------
  406. SCODE CLayoutRootStorage::ProcessRepeatLoop( StorageLayout *pStorageLayout,
  407. DWORD nEntries,
  408. int * nRepeatStart)
  409. {
  410. SCODE sc = S_OK;
  411. int i,
  412. nLoopCount = 0,
  413. nLoopTimes;
  414. BOOL fDone = FALSE,
  415. fUntilDone;
  416. // Are we going to repeat until all streams are read to the end?
  417. if ((nLoopTimes = (LONG) pStorageLayout[*nRepeatStart].cBytes.LowPart) != STG_TOEND)
  418. fUntilDone = FALSE;
  419. else
  420. {
  421. fUntilDone = TRUE;
  422. nLoopTimes = 1;
  423. }
  424. // finished when all streams are completely read, or we have
  425. // looped through the specified amount of times
  426. while ((!fDone)&&(nLoopCount < nLoopTimes))
  427. {
  428. if (!fUntilDone)
  429. nLoopCount ++;
  430. i = *nRepeatStart;
  431. fDone = TRUE;
  432. // STGTY_REPEAT with 0 bytes indicates the end of this repeat block
  433. while (!((pStorageLayout[++i].LayoutType == STGTY_REPEAT ) &&
  434. (pStorageLayout[i].cBytes.QuadPart == 0)) )
  435. {
  436. if (i >= (LONG) nEntries)
  437. {
  438. return E_INVALIDARG;
  439. }
  440. // beginning of another repeat block
  441. if (pStorageLayout[i].LayoutType == STGTY_REPEAT )
  442. {
  443. if ((pStorageLayout[i].pwcsElementName !=NULL) ||
  444. (pStorageLayout[i].cOffset.QuadPart < 0) ||
  445. (pStorageLayout[i].cBytes.QuadPart < 0) )
  446. {
  447. return STG_E_INVALIDPARAMETER;
  448. }
  449. layChk(ProcessRepeatLoop(pStorageLayout,
  450. nEntries,
  451. &i));
  452. }
  453. else
  454. {
  455. layChk(ProcessItem(&(pStorageLayout[i]), &fDone));
  456. }
  457. }
  458. }
  459. *nRepeatStart = i;
  460. Err:
  461. return sc;
  462. }
  463. //+---------------------------------------------------------------------------
  464. //
  465. // Function: CLayoutRootStorage::ProcessLayout
  466. //
  467. // Synopsis: Construct an unprocessed script from an app provided script
  468. //
  469. // Arguments: [pStorageLayout] -- Pointer to storage layout array
  470. // [nEntries] -- Number of entries in the array
  471. // [grfInterleavedFlag] -- Specifies disposition of control
  472. // structures
  473. //
  474. // Returns: Appropriate status code
  475. //
  476. // History: 22-Apr-96 SusiA Created
  477. //
  478. //----------------------------------------------------------------------------
  479. SCODE CLayoutRootStorage::ProcessLayout( StorageLayout *pStorageLayout,
  480. DWORD nEntries,
  481. DWORD glfInterleavedFlag)
  482. {
  483. SCODE sc = S_OK;
  484. int i;
  485. BOOL fUnused;
  486. for (i = 0; i < (LONG) nEntries; i++)
  487. {
  488. if (pStorageLayout[i].LayoutType == STGTY_REPEAT )
  489. {
  490. if (pStorageLayout[i].cBytes.QuadPart != 0)
  491. {
  492. if ((pStorageLayout[i].pwcsElementName !=NULL) ||
  493. (pStorageLayout[i].cOffset.QuadPart < 0) ||
  494. (pStorageLayout[i].cBytes.QuadPart < 0) )
  495. {
  496. return STG_E_INVALIDPARAMETER;
  497. }
  498. layChk(ProcessRepeatLoop(pStorageLayout,
  499. nEntries,
  500. &i));
  501. }
  502. else //end repeat block with no matching beginning
  503. {
  504. sc = E_INVALIDARG;
  505. layChk(sc);
  506. }
  507. }
  508. else // (pStorageLayout[i].LayoutType == STGTY_REPEAT )
  509. {
  510. layChk(ProcessItem(&(pStorageLayout[i]), &fUnused));
  511. }
  512. }
  513. Err:
  514. if (_pStgList)
  515. {
  516. FreeStgList(_pStgList);
  517. _pStgList = NULL;
  518. }
  519. if (_pStmList)
  520. {
  521. FreeStmList(_pStmList);
  522. _pStmList = NULL;
  523. }
  524. return sc;
  525. }