Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define _WIN32_WINNT 0x0501
- #define _UNICODE
- #define UNICODE
- #include <sdkddkver.h>
- /*******************************************************************************
- Includes
- *******************************************************************************/
- #include <stdarg.h>
- #include <stdlib.h>
- #include <string.h>
- #include <windows.h>
- /*******************************************************************************
- Prototypes
- *******************************************************************************/
- // Unzip function
- int UnzipFile(const WCHAR *ZipFilePath, const WCHAR *DestFolder);
- // OLE helper functions
- IDispatch *CreateObject(WCHAR *ProgId);
- IDispatch *InvokeIDispatchMethod(IDispatch *Obj, BSTR MethodName, bool HasRetVal, const WCHAR *Params, ...);
- int InvokeIntProperty(IDispatch *Obj, BSTR PropertyName);
- VARIANT *MakeParams(UINT *cParams, va_list *args, const WCHAR *Params);
- /*******************************************************************************
- Main program
- *******************************************************************************/
- int wmain(int argc, WCHAR *argv[])
- {
- int iRes;
- OleInitialize(NULL);
- iRes = UnzipFile(L"E:\\Src\\AZipFile.zip", L"E:\\Dst");
- OleUninitialize();
- return iRes;
- }
- int UnzipFile(const WCHAR *ZipFilePath, const WCHAR *DestFolder)
- {
- IDispatch *oShell;
- IDispatch *oZipFile;
- IDispatch *oDstFolder;
- IDispatch *oZipItems;
- IDispatch *oDstFolderItems;
- int iRetVal = -1; // Unknown error
- // Create Windows Explorer automation object
- oShell = CreateObject(L"Shell.Application");
- if (!oShell) {iRetVal = 1; goto cleanup2;}
- // Retrieve namespace object of ZIP file (is handled internally as a directory)
- oZipFile = InvokeIDispatchMethod(oShell, L"NameSpace", true, L"%s", ZipFilePath);
- if (!oZipFile) {iRetVal = 2; goto cleanup1;}
- // Retrieve a collection with the items of the ZIP file
- oZipItems = InvokeIDispatchMethod(oZipFile, L"Items", true, NULL);
- if (!oZipItems) {iRetVal = 3; goto cleanup1;}
- // Retrieve namespace object of the destination directory
- oDstFolder = InvokeIDispatchMethod(oShell, L"NameSpace", true, L"%s", DestFolder);
- if (!oDstFolder) {iRetVal = 4; goto cleanup1;}
- // Invoke CopyHere method of the destination directory to extract ZIP content
- // The flag's meaning:
- // 4: Do not display a progress dialog box.
- // 16: Respond with "Yes to All" for any dialog box that is displayed.
- // 512: Do not confirm the creation of a new directory if the operation
- // requires one to be created.
- // 1024: Do not display a user interface if an error occurs.
- if (!InvokeIDispatchMethod(oDstFolder, L"CopyHere", false, L"%o%i", oZipItems, 0x0614))
- {iRetVal = 5; goto cleanup1;}
- // Retrieve a collection with the items in the destination directory
- oDstFolderItems = InvokeIDispatchMethod(oDstFolder, L"Items", true, NULL);
- if (!oDstFolderItems) {iRetVal = 6; goto cleanup1;}
- // Wait until copying has been finished
- while (InvokeIntProperty(oDstFolderItems, L"Count") != InvokeIntProperty(oZipItems, L"Count"))
- Sleep(500);
- // Signal success
- iRetVal = 0;
- cleanup1:
- oShell->Release();
- cleanup2:
- oZipFile->Release();
- oZipItems->Release();
- oDstFolder->Release();
- oDstFolderItems->Release();
- return iRetVal;
- }
- IDispatch *CreateObject(WCHAR *ProgId)
- {
- HRESULT hr;
- CLSID clsid = GUID_NULL;
- IUnknown *pUnk = NULL;
- IDispatch *pDisp = NULL;
- IDispatch *pResult = NULL;
- // Retrieve class id from prog id
- hr = CLSIDFromProgID(ProgId, &clsid);
- if (!SUCCEEDED(hr)) goto quit;
- // Create class instance
- hr = CoCreateInstance(clsid, NULL, CLSCTX_SERVER, IID_IUnknown, (void **) &pUnk);
- if (!SUCCEEDED(hr)) goto quit;
- // Check if we have an object with IDispatch interface
- hr = pUnk->QueryInterface(IID_IDispatch, (void **) &pDisp);
- if (!SUCCEEDED(hr)) goto cleanup;
- pResult = pDisp;
- cleanup:
- pUnk->Release();
- quit:
- return pResult;
- }
- IDispatch *InvokeIDispatchMethod(IDispatch *Obj, BSTR MethodName, bool HasRetVal, const WCHAR *Params, ...)
- {
- HRESULT hr;
- DISPID dispId;
- DISPPARAMS dispParams;
- VARIANT dispRetVal;
- VARIANT *vParams = NULL;
- IDispatch *pDisp = NULL;
- IDispatch *pResult = NULL;
- UINT cParams = 0;
- va_list argptr;
- // Extract parameters from variable argument list and store them into array
- if (Params)
- {
- va_start(argptr, Params);
- vParams = MakeParams(&cParams, &argptr, Params);
- va_end(argptr);
- }
- // Get DispId of method by its name
- hr = Obj->GetIDsOfNames(IID_NULL, &MethodName, 1, LOCALE_USER_DEFAULT, &dispId);
- if (!SUCCEEDED(hr)) goto cleanup;
- // Config parameters
- dispParams = {vParams, NULL, cParams, 0};
- // Config return value
- dispRetVal.vt = VT_DISPATCH;
- dispRetVal.pdispVal = NULL;
- // Call method
- hr = Obj->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD,
- &dispParams, HasRetVal ? &dispRetVal : NULL, NULL, NULL);
- if (!SUCCEEDED(hr)) goto cleanup;
- // Check if method has a return value
- if (!HasRetVal)
- {
- // No -> return 1 to signal success
- pResult = (IDispatch *) 1;
- }
- else
- {
- // Yes -> return object with IDispatch interface
- hr = dispRetVal.pdispVal->QueryInterface(IID_IDispatch, (void **) &pDisp);
- if (!SUCCEEDED(hr)) goto cleanup;
- pResult = pDisp;
- }
- cleanup:
- // Free parameters array
- free(vParams);
- return pResult;
- }
- int InvokeIntProperty(IDispatch *Obj, BSTR PropertyName)
- {
- HRESULT hr;
- DISPID dispId;
- DISPPARAMS dispParams;
- VARIANT dispRetVal;
- int iResult = 0;
- // Get DispId of property by its name
- hr = Obj->GetIDsOfNames(IID_NULL, &PropertyName, 1, LOCALE_USER_DEFAULT, &dispId);
- if (!SUCCEEDED(hr)) goto cleanup;
- // Config parameters
- dispParams = {NULL, NULL, 0, 0};
- // Config return value
- dispRetVal.vt = VT_I4;
- dispRetVal.intVal = NULL;
- // Query property value
- hr = Obj->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
- &dispParams, &dispRetVal, NULL, NULL);
- if (!SUCCEEDED(hr)) goto cleanup;
- // Return query result
- iResult = dispRetVal.intVal;
- cleanup:
- return iResult;
- }
- VARIANT *MakeParams(UINT *cParams, va_list *args, const WCHAR *Params)
- {
- VARIANT *vParams = NULL;
- WCHAR *params = NULL;
- WCHAR *pCh = NULL;
- VARIANT vBuf;
- UINT cnt;
- // Since the format string gets changed below we work with a copy
- params = (WCHAR *) calloc(wcslen(Params) + 1, sizeof(*Params));
- wcscpy(params, Params);
- // Tokenize format string
- *cParams = 0;
- pCh = wcstok(params, L"%");
- while (pCh)
- {
- // Allocate new VARIANT for currently processed parameter
- vParams = (VARIANT *) realloc(vParams, ++*cParams * sizeof(*vParams));
- // Config VARIANT according to parameter's type
- switch(*pCh)
- {
- // Integer
- case L'i':
- case L'd':
- vParams[*cParams-1].vt = VT_I4;
- vParams[*cParams-1].intVal = va_arg(*args, int);;
- break;
- // String
- case L's':
- vParams[*cParams-1].vt = VT_BSTR;
- vParams[*cParams-1].bstrVal = va_arg(*args, WCHAR *);
- break;
- // Object with IDispatch interface
- case L'o':
- vParams[*cParams-1].vt = VT_DISPATCH;
- vParams[*cParams-1].pdispVal = va_arg(*args, IDispatch *);
- break;
- // Unknown parameter type
- default:
- // Assume we have to skip an unknown parameter of type integer
- va_arg(*args, int);
- vParams = (VARIANT *) realloc(vParams, --*cParams * sizeof(*vParams));
- break;
- }
- // Retrieve next token
- pCh = wcstok(NULL, L"%");
- }
- // COM expects parameters in revers order, i.e. rightmost parameter has to be
- // the first in the array
- for (cnt = 0; cnt < (*cParams + 1) / 2; cnt++)
- {
- vBuf = vParams[cnt];
- vParams[cnt] = vParams[*cParams-1-cnt];
- vParams[*cParams-1-cnt] = vBuf;
- }
- // Free copy of format string
- free(params);
- return vParams;
- }
Add Comment
Please, Sign In to add comment