Guest User

Untitled

a guest
Dec 18th, 2018
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.90 KB | None | 0 0
  1. #define _WIN32_WINNT 0x0501
  2.  
  3. #define _UNICODE
  4. #define UNICODE
  5.  
  6. #include <sdkddkver.h>
  7.  
  8.  
  9. /*******************************************************************************
  10. Includes
  11. *******************************************************************************/
  12.  
  13. #include <stdarg.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <windows.h>
  17.  
  18.  
  19.  
  20. /*******************************************************************************
  21. Prototypes
  22. *******************************************************************************/
  23.  
  24. // Unzip function
  25. int UnzipFile(const WCHAR *ZipFilePath, const WCHAR *DestFolder);
  26.  
  27. // OLE helper functions
  28. IDispatch *CreateObject(WCHAR *ProgId);
  29. IDispatch *InvokeIDispatchMethod(IDispatch *Obj, BSTR MethodName, bool HasRetVal, const WCHAR *Params, ...);
  30. int InvokeIntProperty(IDispatch *Obj, BSTR PropertyName);
  31. VARIANT *MakeParams(UINT *cParams, va_list *args, const WCHAR *Params);
  32.  
  33.  
  34.  
  35. /*******************************************************************************
  36. Main program
  37. *******************************************************************************/
  38.  
  39. int wmain(int argc, WCHAR *argv[])
  40. {
  41. int iRes;
  42.  
  43. OleInitialize(NULL);
  44. iRes = UnzipFile(L"E:\\Src\\AZipFile.zip", L"E:\\Dst");
  45. OleUninitialize();
  46.  
  47. return iRes;
  48. }
  49.  
  50.  
  51. int UnzipFile(const WCHAR *ZipFilePath, const WCHAR *DestFolder)
  52. {
  53. IDispatch *oShell;
  54. IDispatch *oZipFile;
  55. IDispatch *oDstFolder;
  56. IDispatch *oZipItems;
  57. IDispatch *oDstFolderItems;
  58. int iRetVal = -1; // Unknown error
  59.  
  60. // Create Windows Explorer automation object
  61. oShell = CreateObject(L"Shell.Application");
  62. if (!oShell) {iRetVal = 1; goto cleanup2;}
  63.  
  64. // Retrieve namespace object of ZIP file (is handled internally as a directory)
  65. oZipFile = InvokeIDispatchMethod(oShell, L"NameSpace", true, L"%s", ZipFilePath);
  66. if (!oZipFile) {iRetVal = 2; goto cleanup1;}
  67.  
  68. // Retrieve a collection with the items of the ZIP file
  69. oZipItems = InvokeIDispatchMethod(oZipFile, L"Items", true, NULL);
  70. if (!oZipItems) {iRetVal = 3; goto cleanup1;}
  71.  
  72. // Retrieve namespace object of the destination directory
  73. oDstFolder = InvokeIDispatchMethod(oShell, L"NameSpace", true, L"%s", DestFolder);
  74. if (!oDstFolder) {iRetVal = 4; goto cleanup1;}
  75.  
  76. // Invoke CopyHere method of the destination directory to extract ZIP content
  77. // The flag's meaning:
  78. // 4: Do not display a progress dialog box.
  79. // 16: Respond with "Yes to All" for any dialog box that is displayed.
  80. // 512: Do not confirm the creation of a new directory if the operation
  81. // requires one to be created.
  82. // 1024: Do not display a user interface if an error occurs.
  83. if (!InvokeIDispatchMethod(oDstFolder, L"CopyHere", false, L"%o%i", oZipItems, 0x0614))
  84. {iRetVal = 5; goto cleanup1;}
  85.  
  86. // Retrieve a collection with the items in the destination directory
  87. oDstFolderItems = InvokeIDispatchMethod(oDstFolder, L"Items", true, NULL);
  88. if (!oDstFolderItems) {iRetVal = 6; goto cleanup1;}
  89.  
  90. // Wait until copying has been finished
  91. while (InvokeIntProperty(oDstFolderItems, L"Count") != InvokeIntProperty(oZipItems, L"Count"))
  92. Sleep(500);
  93.  
  94. // Signal success
  95. iRetVal = 0;
  96.  
  97. cleanup1:
  98. oShell->Release();
  99.  
  100. cleanup2:
  101. oZipFile->Release();
  102. oZipItems->Release();
  103. oDstFolder->Release();
  104. oDstFolderItems->Release();
  105.  
  106. return iRetVal;
  107. }
  108.  
  109.  
  110. IDispatch *CreateObject(WCHAR *ProgId)
  111. {
  112. HRESULT hr;
  113. CLSID clsid = GUID_NULL;
  114. IUnknown *pUnk = NULL;
  115. IDispatch *pDisp = NULL;
  116. IDispatch *pResult = NULL;
  117.  
  118. // Retrieve class id from prog id
  119. hr = CLSIDFromProgID(ProgId, &clsid);
  120. if (!SUCCEEDED(hr)) goto quit;
  121.  
  122. // Create class instance
  123. hr = CoCreateInstance(clsid, NULL, CLSCTX_SERVER, IID_IUnknown, (void **) &pUnk);
  124. if (!SUCCEEDED(hr)) goto quit;
  125.  
  126. // Check if we have an object with IDispatch interface
  127. hr = pUnk->QueryInterface(IID_IDispatch, (void **) &pDisp);
  128. if (!SUCCEEDED(hr)) goto cleanup;
  129.  
  130. pResult = pDisp;
  131.  
  132. cleanup:
  133. pUnk->Release();
  134.  
  135. quit:
  136. return pResult;
  137. }
  138.  
  139.  
  140. IDispatch *InvokeIDispatchMethod(IDispatch *Obj, BSTR MethodName, bool HasRetVal, const WCHAR *Params, ...)
  141. {
  142. HRESULT hr;
  143. DISPID dispId;
  144. DISPPARAMS dispParams;
  145. VARIANT dispRetVal;
  146. VARIANT *vParams = NULL;
  147. IDispatch *pDisp = NULL;
  148. IDispatch *pResult = NULL;
  149. UINT cParams = 0;
  150. va_list argptr;
  151.  
  152. // Extract parameters from variable argument list and store them into array
  153. if (Params)
  154. {
  155. va_start(argptr, Params);
  156. vParams = MakeParams(&cParams, &argptr, Params);
  157. va_end(argptr);
  158. }
  159.  
  160. // Get DispId of method by its name
  161. hr = Obj->GetIDsOfNames(IID_NULL, &MethodName, 1, LOCALE_USER_DEFAULT, &dispId);
  162. if (!SUCCEEDED(hr)) goto cleanup;
  163.  
  164. // Config parameters
  165. dispParams = {vParams, NULL, cParams, 0};
  166.  
  167. // Config return value
  168. dispRetVal.vt = VT_DISPATCH;
  169. dispRetVal.pdispVal = NULL;
  170.  
  171. // Call method
  172. hr = Obj->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD,
  173. &dispParams, HasRetVal ? &dispRetVal : NULL, NULL, NULL);
  174. if (!SUCCEEDED(hr)) goto cleanup;
  175.  
  176. // Check if method has a return value
  177. if (!HasRetVal)
  178. {
  179. // No -> return 1 to signal success
  180. pResult = (IDispatch *) 1;
  181. }
  182. else
  183. {
  184. // Yes -> return object with IDispatch interface
  185. hr = dispRetVal.pdispVal->QueryInterface(IID_IDispatch, (void **) &pDisp);
  186. if (!SUCCEEDED(hr)) goto cleanup;
  187.  
  188. pResult = pDisp;
  189. }
  190.  
  191. cleanup:
  192. // Free parameters array
  193. free(vParams);
  194.  
  195. return pResult;
  196. }
  197.  
  198.  
  199. int InvokeIntProperty(IDispatch *Obj, BSTR PropertyName)
  200. {
  201. HRESULT hr;
  202. DISPID dispId;
  203. DISPPARAMS dispParams;
  204. VARIANT dispRetVal;
  205. int iResult = 0;
  206.  
  207. // Get DispId of property by its name
  208. hr = Obj->GetIDsOfNames(IID_NULL, &PropertyName, 1, LOCALE_USER_DEFAULT, &dispId);
  209. if (!SUCCEEDED(hr)) goto cleanup;
  210.  
  211. // Config parameters
  212. dispParams = {NULL, NULL, 0, 0};
  213.  
  214. // Config return value
  215. dispRetVal.vt = VT_I4;
  216. dispRetVal.intVal = NULL;
  217.  
  218. // Query property value
  219. hr = Obj->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
  220. &dispParams, &dispRetVal, NULL, NULL);
  221. if (!SUCCEEDED(hr)) goto cleanup;
  222.  
  223. // Return query result
  224. iResult = dispRetVal.intVal;
  225.  
  226. cleanup:
  227. return iResult;
  228. }
  229.  
  230.  
  231. VARIANT *MakeParams(UINT *cParams, va_list *args, const WCHAR *Params)
  232. {
  233. VARIANT *vParams = NULL;
  234. WCHAR *params = NULL;
  235. WCHAR *pCh = NULL;
  236. VARIANT vBuf;
  237. UINT cnt;
  238.  
  239. // Since the format string gets changed below we work with a copy
  240. params = (WCHAR *) calloc(wcslen(Params) + 1, sizeof(*Params));
  241. wcscpy(params, Params);
  242.  
  243. // Tokenize format string
  244. *cParams = 0;
  245. pCh = wcstok(params, L"%");
  246.  
  247. while (pCh)
  248. {
  249. // Allocate new VARIANT for currently processed parameter
  250. vParams = (VARIANT *) realloc(vParams, ++*cParams * sizeof(*vParams));
  251.  
  252. // Config VARIANT according to parameter's type
  253. switch(*pCh)
  254. {
  255. // Integer
  256. case L'i':
  257. case L'd':
  258. vParams[*cParams-1].vt = VT_I4;
  259. vParams[*cParams-1].intVal = va_arg(*args, int);;
  260. break;
  261.  
  262. // String
  263. case L's':
  264. vParams[*cParams-1].vt = VT_BSTR;
  265. vParams[*cParams-1].bstrVal = va_arg(*args, WCHAR *);
  266. break;
  267.  
  268. // Object with IDispatch interface
  269. case L'o':
  270. vParams[*cParams-1].vt = VT_DISPATCH;
  271. vParams[*cParams-1].pdispVal = va_arg(*args, IDispatch *);
  272. break;
  273.  
  274. // Unknown parameter type
  275. default:
  276. // Assume we have to skip an unknown parameter of type integer
  277. va_arg(*args, int);
  278. vParams = (VARIANT *) realloc(vParams, --*cParams * sizeof(*vParams));
  279. break;
  280. }
  281.  
  282. // Retrieve next token
  283. pCh = wcstok(NULL, L"%");
  284. }
  285.  
  286. // COM expects parameters in revers order, i.e. rightmost parameter has to be
  287. // the first in the array
  288. for (cnt = 0; cnt < (*cParams + 1) / 2; cnt++)
  289. {
  290. vBuf = vParams[cnt];
  291.  
  292. vParams[cnt] = vParams[*cParams-1-cnt];
  293. vParams[*cParams-1-cnt] = vBuf;
  294. }
  295.  
  296. // Free copy of format string
  297. free(params);
  298.  
  299. return vParams;
  300. }
Add Comment
Please, Sign In to add comment