testShell.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. import sys, os
  2. import struct
  3. import unittest
  4. import copy
  5. import datetime
  6. import win32timezone
  7. try:
  8. sys_maxsize = sys.maxsize # 2.6 and later - maxsize != maxint on 64bits
  9. except AttributeError:
  10. sys_maxsize = sys.maxint
  11. import win32con
  12. import pythoncom
  13. import pywintypes
  14. from win32com.shell import shell
  15. from win32com.shell.shellcon import *
  16. from win32com.storagecon import *
  17. import win32com.test.util
  18. from pywin32_testutil import str2bytes
  19. class ShellTester(win32com.test.util.TestCase):
  20. def testShellLink(self):
  21. desktop = str(shell.SHGetSpecialFolderPath(0, CSIDL_DESKTOP))
  22. num = 0
  23. shellLink = pythoncom.CoCreateInstance(shell.CLSID_ShellLink, None, pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IShellLink)
  24. persistFile = shellLink.QueryInterface(pythoncom.IID_IPersistFile)
  25. names = [os.path.join(desktop, n) for n in os.listdir(desktop)]
  26. programs = str(shell.SHGetSpecialFolderPath(0, CSIDL_PROGRAMS))
  27. names.extend([os.path.join(programs, n) for n in os.listdir(programs)])
  28. for name in names:
  29. try:
  30. persistFile.Load(name,STGM_READ)
  31. except pythoncom.com_error:
  32. continue
  33. # Resolve is slow - avoid it for our tests.
  34. #shellLink.Resolve(0, shell.SLR_ANY_MATCH | shell.SLR_NO_UI)
  35. fname, findData = shellLink.GetPath(0)
  36. unc = shellLink.GetPath(shell.SLGP_UNCPRIORITY)[0]
  37. num += 1
  38. if num == 0:
  39. # This isn't a fatal error, but is unlikely.
  40. print("Could not find any links on your desktop or programs dir, which is unusual")
  41. def testShellFolder(self):
  42. sf = shell.SHGetDesktopFolder()
  43. names_1 = []
  44. for i in sf: # Magically calls EnumObjects
  45. name = sf.GetDisplayNameOf(i, SHGDN_NORMAL)
  46. names_1.append(name)
  47. # And get the enumerator manually
  48. enum = sf.EnumObjects(0, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN)
  49. names_2 = []
  50. for i in enum:
  51. name = sf.GetDisplayNameOf(i, SHGDN_NORMAL)
  52. names_2.append(name)
  53. names_1.sort()
  54. names_2.sort()
  55. self.assertEqual(names_1, names_2)
  56. class PIDLTester(win32com.test.util.TestCase):
  57. def _rtPIDL(self, pidl):
  58. pidl_str = shell.PIDLAsString(pidl)
  59. pidl_rt = shell.StringAsPIDL(pidl_str)
  60. self.assertEqual(pidl_rt, pidl)
  61. pidl_str_rt = shell.PIDLAsString(pidl_rt)
  62. self.assertEqual(pidl_str_rt, pidl_str)
  63. def _rtCIDA(self, parent, kids):
  64. cida = parent, kids
  65. cida_str = shell.CIDAAsString(cida)
  66. cida_rt = shell.StringAsCIDA(cida_str)
  67. self.assertEqual(cida, cida_rt)
  68. cida_str_rt = shell.CIDAAsString(cida_rt)
  69. self.assertEqual(cida_str_rt, cida_str)
  70. def testPIDL(self):
  71. # A PIDL of "\1" is: cb pidl cb
  72. expect = str2bytes("\03\00" "\1" "\0\0")
  73. self.assertEqual(shell.PIDLAsString([str2bytes("\1")]), expect)
  74. self._rtPIDL([str2bytes("\0")])
  75. self._rtPIDL([str2bytes("\1"), str2bytes("\2"), str2bytes("\3")])
  76. self._rtPIDL([str2bytes("\0") * 2048] * 2048)
  77. # PIDL must be a list
  78. self.assertRaises(TypeError, shell.PIDLAsString, "foo")
  79. def testCIDA(self):
  80. self._rtCIDA([str2bytes("\0")], [ [str2bytes("\0")] ])
  81. self._rtCIDA([str2bytes("\1")], [ [str2bytes("\2")] ])
  82. self._rtCIDA([str2bytes("\0")], [ [str2bytes("\0")], [str2bytes("\1")], [str2bytes("\2")] ])
  83. def testBadShortPIDL(self):
  84. # A too-short child element: cb pidl cb
  85. pidl = str2bytes("\01\00" "\1")
  86. self.assertRaises(ValueError, shell.StringAsPIDL, pidl)
  87. # ack - tried to test too long PIDLs, but a len of 0xFFFF may not
  88. # always fail.
  89. class FILEGROUPDESCRIPTORTester(win32com.test.util.TestCase):
  90. def _getTestTimes(self):
  91. if issubclass(pywintypes.TimeType, datetime.datetime):
  92. ctime = win32timezone.now()
  93. # FILETIME only has ms precision...
  94. ctime = ctime.replace(microsecond=ctime.microsecond // 1000 * 1000)
  95. atime = ctime + datetime.timedelta(seconds=1)
  96. wtime = atime + datetime.timedelta(seconds=1)
  97. else:
  98. ctime = pywintypes.Time(11)
  99. atime = pywintypes.Time(12)
  100. wtime = pywintypes.Time(13)
  101. return ctime, atime, wtime
  102. def _testRT(self, fd):
  103. fgd_string = shell.FILEGROUPDESCRIPTORAsString([fd])
  104. fd2 = shell.StringAsFILEGROUPDESCRIPTOR(fgd_string)[0]
  105. fd = fd.copy()
  106. fd2 = fd2.copy()
  107. # The returned objects *always* have dwFlags and cFileName.
  108. if 'dwFlags' not in fd:
  109. del fd2['dwFlags']
  110. if 'cFileName' not in fd:
  111. self.assertEqual(fd2['cFileName'], '')
  112. del fd2['cFileName']
  113. self.assertEqual(fd, fd2)
  114. def _testSimple(self, make_unicode):
  115. fgd = shell.FILEGROUPDESCRIPTORAsString([], make_unicode)
  116. header = struct.pack("i", 0)
  117. self.assertEqual(header, fgd[:len(header)])
  118. self._testRT(dict())
  119. d = dict()
  120. fgd = shell.FILEGROUPDESCRIPTORAsString([d], make_unicode)
  121. header = struct.pack("i", 1)
  122. self.assertEqual(header, fgd[:len(header)])
  123. self._testRT(d)
  124. def testSimpleBytes(self):
  125. self._testSimple(False)
  126. def testSimpleUnicode(self):
  127. self._testSimple(True)
  128. def testComplex(self):
  129. clsid = pythoncom.MakeIID("{CD637886-DB8B-4b04-98B5-25731E1495BE}")
  130. ctime, atime, wtime = self._getTestTimes()
  131. d = dict(cFileName="foo.txt",
  132. clsid=clsid,
  133. sizel=(1,2),
  134. pointl=(3,4),
  135. dwFileAttributes = win32con.FILE_ATTRIBUTE_NORMAL,
  136. ftCreationTime=ctime,
  137. ftLastAccessTime=atime,
  138. ftLastWriteTime=wtime,
  139. nFileSize=sys_maxsize + 1)
  140. self._testRT(d)
  141. def testUnicode(self):
  142. # exercise a bug fixed in build 210 - multiple unicode objects failed.
  143. ctime, atime, wtime = self._getTestTimes()
  144. d = [dict(cFileName="foo.txt",
  145. sizel=(1,2),
  146. pointl=(3,4),
  147. dwFileAttributes = win32con.FILE_ATTRIBUTE_NORMAL,
  148. ftCreationTime=ctime,
  149. ftLastAccessTime=atime,
  150. ftLastWriteTime=wtime,
  151. nFileSize=sys_maxsize + 1),
  152. dict(cFileName="foo2.txt",
  153. sizel=(1,2),
  154. pointl=(3,4),
  155. dwFileAttributes = win32con.FILE_ATTRIBUTE_NORMAL,
  156. ftCreationTime=ctime,
  157. ftLastAccessTime=atime,
  158. ftLastWriteTime=wtime,
  159. nFileSize=sys_maxsize + 1),
  160. dict(cFileName="foo\xa9.txt",
  161. sizel=(1,2),
  162. pointl=(3,4),
  163. dwFileAttributes = win32con.FILE_ATTRIBUTE_NORMAL,
  164. ftCreationTime=ctime,
  165. ftLastAccessTime=atime,
  166. ftLastWriteTime=wtime,
  167. nFileSize=sys_maxsize + 1),
  168. ]
  169. s = shell.FILEGROUPDESCRIPTORAsString(d, 1)
  170. d2 = shell.StringAsFILEGROUPDESCRIPTOR(s)
  171. # clobber 'dwFlags' - they are not expected to be identical
  172. for t in d2:
  173. del t['dwFlags']
  174. self.assertEqual(d, d2)
  175. class FileOperationTester(win32com.test.util.TestCase):
  176. def setUp(self):
  177. import tempfile
  178. self.src_name = os.path.join(tempfile.gettempdir(), "pywin32_testshell")
  179. self.dest_name = os.path.join(tempfile.gettempdir(), "pywin32_testshell_dest")
  180. self.test_data = str2bytes("Hello from\0Python")
  181. f=open(self.src_name, "wb")
  182. f.write(self.test_data)
  183. f.close()
  184. try:
  185. os.unlink(self.dest_name)
  186. except os.error:
  187. pass
  188. def tearDown(self):
  189. for fname in (self.src_name, self.dest_name):
  190. if os.path.isfile(fname):
  191. os.unlink(fname)
  192. def testCopy(self):
  193. s = (0, # hwnd,
  194. FO_COPY, #operation
  195. self.src_name,
  196. self.dest_name)
  197. rc, aborted = shell.SHFileOperation(s)
  198. self.failUnless(not aborted)
  199. self.failUnlessEqual(0, rc)
  200. self.failUnless(os.path.isfile(self.src_name))
  201. self.failUnless(os.path.isfile(self.dest_name))
  202. def testRename(self):
  203. s = (0, # hwnd,
  204. FO_RENAME, #operation
  205. self.src_name,
  206. self.dest_name)
  207. rc, aborted = shell.SHFileOperation(s)
  208. self.failUnless(not aborted)
  209. self.failUnlessEqual(0, rc)
  210. self.failUnless(os.path.isfile(self.dest_name))
  211. self.failUnless(not os.path.isfile(self.src_name))
  212. def testMove(self):
  213. s = (0, # hwnd,
  214. FO_MOVE, #operation
  215. self.src_name,
  216. self.dest_name)
  217. rc, aborted = shell.SHFileOperation(s)
  218. self.failUnless(not aborted)
  219. self.failUnlessEqual(0, rc)
  220. self.failUnless(os.path.isfile(self.dest_name))
  221. self.failUnless(not os.path.isfile(self.src_name))
  222. def testDelete(self):
  223. s = (0, # hwnd,
  224. FO_DELETE, #operation
  225. self.src_name, None,
  226. FOF_NOCONFIRMATION)
  227. rc, aborted = shell.SHFileOperation(s)
  228. self.failUnless(not aborted)
  229. self.failUnlessEqual(0, rc)
  230. self.failUnless(not os.path.isfile(self.src_name))
  231. if __name__=='__main__':
  232. win32com.test.util.testmain()